mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-04 02:57:46 +00:00
Compare commits
31 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3b68f8f16a | |||
| fca2de21b1 | |||
| 107b1c2906 | |||
| 2409bbef69 | |||
| 8b078a9e8f | |||
| 9e24441978 | |||
| 1e6c14b3e4 | |||
| 25f6be1488 | |||
| 9a9106a297 | |||
| a68f7e4ce3 | |||
| 70b3ece6ec | |||
| 86ea216e7d | |||
| 5a92c35536 | |||
| 7513fa2c96 | |||
| bc946f346d | |||
| 6e6666519c | |||
| cecae8084c | |||
| 9720ccacbb | |||
| a5aa777c7b | |||
| aca1ad187d | |||
| 5a41ed6329 | |||
| 91e9c84d85 | |||
| 4af530f238 | |||
| d3863f337d | |||
| 5551ec7a1e | |||
| 91104b2f27 | |||
| 80f38e8449 | |||
| 22893c5180 | |||
| 9e4e182615 | |||
| 5f96d2b784 | |||
| bd1d93b705 |
+1
-10
@@ -118,13 +118,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- test-linux:
|
- test-linux:
|
||||||
llvm: "14"
|
llvm: "14"
|
||||||
test-llvm14-go119:
|
resource_class: large
|
||||||
docker:
|
|
||||||
- image: golang:1.19beta1-buster
|
|
||||||
steps:
|
|
||||||
- test-linux:
|
|
||||||
llvm: "14"
|
|
||||||
fmt-check: false
|
|
||||||
|
|
||||||
workflows:
|
workflows:
|
||||||
test-all:
|
test-all:
|
||||||
@@ -132,6 +126,3 @@ workflows:
|
|||||||
# This tests our lowest supported versions of Go and LLVM, to make sure at
|
# This tests our lowest supported versions of Go and LLVM, to make sure at
|
||||||
# least the smoke tests still pass.
|
# least the smoke tests still pass.
|
||||||
- test-llvm14-go118
|
- test-llvm14-go118
|
||||||
# This tests a beta version of Go. It should be removed once regular
|
|
||||||
# release builds are built using this version.
|
|
||||||
- test-llvm14-go119
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ jobs:
|
|||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: '1.18.1'
|
go-version: '1.19'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Cache LLVM source
|
- name: Cache LLVM source
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
@@ -114,7 +114,7 @@ jobs:
|
|||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: '1.18'
|
go-version: '1.19'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Build TinyGo
|
- name: Build TinyGo
|
||||||
run: go install
|
run: go install
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ jobs:
|
|||||||
# statically linked binary.
|
# statically linked binary.
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
image: golang:1.18-alpine
|
image: golang:1.19-alpine
|
||||||
steps:
|
steps:
|
||||||
- name: Install apk dependencies
|
- name: Install apk dependencies
|
||||||
# tar: needed for actions/cache@v3
|
# tar: needed for actions/cache@v3
|
||||||
@@ -118,7 +118,7 @@ jobs:
|
|||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: '1.18.1'
|
go-version: '1.19'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Install wasmtime
|
- name: Install wasmtime
|
||||||
run: |
|
run: |
|
||||||
@@ -171,7 +171,7 @@ jobs:
|
|||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: '1.18.1'
|
go-version: '1.19'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Install Node.js
|
- name: Install Node.js
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v2
|
||||||
@@ -271,7 +271,7 @@ jobs:
|
|||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: '1.18.1'
|
go-version: '1.19'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Cache LLVM source
|
- name: Cache LLVM source
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
@@ -371,7 +371,7 @@ jobs:
|
|||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: '1.18.1'
|
go-version: '1.19'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Cache LLVM source
|
- name: Cache LLVM source
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ jobs:
|
|||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: '1.18.1'
|
go-version: '1.19'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Cache LLVM source
|
- name: Cache LLVM source
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
# tinygo-llvm stage obtains the llvm source for TinyGo
|
# tinygo-llvm stage obtains the llvm source for TinyGo
|
||||||
FROM golang:1.18 AS tinygo-llvm
|
FROM golang:1.19 AS tinygo-llvm
|
||||||
|
|
||||||
RUN apt-get update && \
|
RUN apt-get update && \
|
||||||
apt-get install -y apt-utils make cmake clang-11 binutils-avr gcc-avr avr-libc ninja-build
|
apt-get install -y apt-utils make cmake clang-11 binutils-avr gcc-avr avr-libc ninja-build
|
||||||
|
|||||||
@@ -330,7 +330,6 @@ endif
|
|||||||
# compress/lzw appears to hang on wasi
|
# compress/lzw appears to hang on wasi
|
||||||
# crypto/hmac fails on wasi, it exits with a "slice out of range" panic
|
# crypto/hmac fails on wasi, it exits with a "slice out of range" panic
|
||||||
# debug/plan9obj requires os.ReadAt, which is not yet supported on windows
|
# debug/plan9obj requires os.ReadAt, which is not yet supported on windows
|
||||||
# io/fs requires os.ReadDir, which is not yet supported on windows or wasi
|
|
||||||
# io/ioutil requires os.ReadDir, which is not yet supported on windows or wasi
|
# io/ioutil requires os.ReadDir, which is not yet supported on windows or wasi
|
||||||
# strconv requires recover() which is not yet supported on wasi
|
# strconv requires recover() which is not yet supported on wasi
|
||||||
# text/template/parse requires recover(), which is not yet supported on wasi
|
# text/template/parse requires recover(), which is not yet supported on wasi
|
||||||
@@ -344,7 +343,6 @@ TEST_PACKAGES_LINUX := \
|
|||||||
crypto/hmac \
|
crypto/hmac \
|
||||||
debug/dwarf \
|
debug/dwarf \
|
||||||
debug/plan9obj \
|
debug/plan9obj \
|
||||||
io/fs \
|
|
||||||
io/ioutil \
|
io/ioutil \
|
||||||
strconv \
|
strconv \
|
||||||
testing/fstest \
|
testing/fstest \
|
||||||
@@ -373,12 +371,15 @@ report-stdlib-tests-pass:
|
|||||||
# Standard library packages that pass tests quickly on the current platform
|
# Standard library packages that pass tests quickly on the current platform
|
||||||
ifeq ($(shell uname),Darwin)
|
ifeq ($(shell uname),Darwin)
|
||||||
TEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_DARWIN)
|
TEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_DARWIN)
|
||||||
|
TEST_IOFS := true
|
||||||
endif
|
endif
|
||||||
ifeq ($(shell uname),Linux)
|
ifeq ($(shell uname),Linux)
|
||||||
TEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_LINUX)
|
TEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_LINUX)
|
||||||
|
TEST_IOFS := true
|
||||||
endif
|
endif
|
||||||
ifeq ($(OS),Windows_NT)
|
ifeq ($(OS),Windows_NT)
|
||||||
TEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_WINDOWS)
|
TEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_WINDOWS)
|
||||||
|
TEST_IOFS := false
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Test known-working standard library packages.
|
# Test known-working standard library packages.
|
||||||
@@ -386,6 +387,12 @@ endif
|
|||||||
.PHONY: tinygo-test
|
.PHONY: tinygo-test
|
||||||
tinygo-test:
|
tinygo-test:
|
||||||
$(TINYGO) test $(TEST_PACKAGES_HOST) $(TEST_PACKAGES_SLOW)
|
$(TINYGO) test $(TEST_PACKAGES_HOST) $(TEST_PACKAGES_SLOW)
|
||||||
|
@# io/fs requires os.ReadDir, not yet supported on windows or wasi. It also
|
||||||
|
@# requires a large stack-size. Hence, io/fs is only run conditionally.
|
||||||
|
@# For more details, see the comments on issue #3143.
|
||||||
|
ifeq ($(TEST_IOFS),true)
|
||||||
|
$(TINYGO) test -stack-size=6MB io/fs
|
||||||
|
endif
|
||||||
tinygo-test-fast:
|
tinygo-test-fast:
|
||||||
$(TINYGO) test $(TEST_PACKAGES_HOST)
|
$(TINYGO) test $(TEST_PACKAGES_HOST)
|
||||||
tinygo-bench:
|
tinygo-bench:
|
||||||
@@ -611,7 +618,7 @@ endif
|
|||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=challenger-rp2040 examples/blinky1
|
$(TINYGO) build -size short -o test.hex -target=challenger-rp2040 examples/blinky1
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=trinkey-qt2040 examples/adc_rp2040
|
$(TINYGO) build -size short -o test.hex -target=trinkey-qt2040 examples/temp
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
# test pwm
|
# test pwm
|
||||||
$(TINYGO) build -size short -o test.hex -target=itsybitsy-m0 examples/pwm
|
$(TINYGO) build -size short -o test.hex -target=itsybitsy-m0 examples/pwm
|
||||||
|
|||||||
+1
-1
@@ -178,7 +178,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
|||||||
|
|
||||||
Scheduler: config.Scheduler(),
|
Scheduler: config.Scheduler(),
|
||||||
AutomaticStackSize: config.AutomaticStackSize(),
|
AutomaticStackSize: config.AutomaticStackSize(),
|
||||||
DefaultStackSize: config.Target.DefaultStackSize,
|
DefaultStackSize: config.StackSize(),
|
||||||
NeedsStackObjects: config.NeedsStackObjects(),
|
NeedsStackObjects: config.NeedsStackObjects(),
|
||||||
Debug: true,
|
Debug: true,
|
||||||
}
|
}
|
||||||
|
|||||||
+57
-16
@@ -32,6 +32,7 @@ type cgoPackage struct {
|
|||||||
errors []error
|
errors []error
|
||||||
currentDir string // current working directory
|
currentDir string // current working directory
|
||||||
packageDir string // full path to the package to process
|
packageDir string // full path to the package to process
|
||||||
|
importPath string
|
||||||
fset *token.FileSet
|
fset *token.FileSet
|
||||||
tokenFiles map[string]*token.File
|
tokenFiles map[string]*token.File
|
||||||
definedGlobally map[string]ast.Node
|
definedGlobally map[string]ast.Node
|
||||||
@@ -39,12 +40,15 @@ type cgoPackage struct {
|
|||||||
cflags []string // CFlags from #cgo lines
|
cflags []string // CFlags from #cgo lines
|
||||||
ldflags []string // LDFlags from #cgo lines
|
ldflags []string // LDFlags from #cgo lines
|
||||||
visitedFiles map[string][]byte
|
visitedFiles map[string][]byte
|
||||||
|
cgoHeaders []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// cgoFile holds information only for a single Go file (with one or more
|
// cgoFile holds information only for a single Go file (with one or more
|
||||||
// `import "C"` statements).
|
// `import "C"` statements).
|
||||||
type cgoFile struct {
|
type cgoFile struct {
|
||||||
*cgoPackage
|
*cgoPackage
|
||||||
|
file *ast.File
|
||||||
|
index int
|
||||||
defined map[string]ast.Node
|
defined map[string]ast.Node
|
||||||
names map[string]clangCursor
|
names map[string]clangCursor
|
||||||
}
|
}
|
||||||
@@ -158,9 +162,10 @@ func GoBytes(ptr unsafe.Pointer, length C.int) []byte {
|
|||||||
// functions), the CFLAGS and LDFLAGS found in #cgo lines, and a map of file
|
// functions), the CFLAGS and LDFLAGS found in #cgo lines, and a map of file
|
||||||
// hashes of the accessed C header files. If there is one or more error, it
|
// hashes of the accessed C header files. If there is one or more error, it
|
||||||
// returns these in the []error slice but still modifies the AST.
|
// returns these in the []error slice but still modifies the AST.
|
||||||
func Process(files []*ast.File, dir string, fset *token.FileSet, cflags []string, clangHeaders string) (*ast.File, []string, []string, []string, map[string][]byte, []error) {
|
func Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cflags []string, clangHeaders string) (*ast.File, []string, []string, []string, map[string][]byte, []error) {
|
||||||
p := &cgoPackage{
|
p := &cgoPackage{
|
||||||
currentDir: dir,
|
currentDir: dir,
|
||||||
|
importPath: importPath,
|
||||||
fset: fset,
|
fset: fset,
|
||||||
tokenFiles: map[string]*token.File{},
|
tokenFiles: map[string]*token.File{},
|
||||||
definedGlobally: map[string]ast.Node{},
|
definedGlobally: map[string]ast.Node{},
|
||||||
@@ -210,13 +215,13 @@ func Process(files []*ast.File, dir string, fset *token.FileSet, cflags []string
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Patch some types, for example *C.char in C.CString.
|
// Patch some types, for example *C.char in C.CString.
|
||||||
cf := p.newCGoFile()
|
cf := p.newCGoFile(nil, -1) // dummy *cgoFile for the walker
|
||||||
astutil.Apply(p.generated, func(cursor *astutil.Cursor) bool {
|
astutil.Apply(p.generated, func(cursor *astutil.Cursor) bool {
|
||||||
return cf.walker(cursor, nil)
|
return cf.walker(cursor, nil)
|
||||||
}, nil)
|
}, nil)
|
||||||
|
|
||||||
// Find `import "C"` C fragments in the file.
|
// Find `import "C"` C fragments in the file.
|
||||||
cgoHeaders := make([]string, len(files)) // combined CGo header fragment for each file
|
p.cgoHeaders = make([]string, len(files)) // combined CGo header fragment for each file
|
||||||
for i, f := range files {
|
for i, f := range files {
|
||||||
var cgoHeader string
|
var cgoHeader string
|
||||||
for i := 0; i < len(f.Decls); i++ {
|
for i := 0; i < len(f.Decls); i++ {
|
||||||
@@ -275,7 +280,7 @@ func Process(files []*ast.File, dir string, fset *token.FileSet, cflags []string
|
|||||||
cgoHeader += fragment
|
cgoHeader += fragment
|
||||||
}
|
}
|
||||||
|
|
||||||
cgoHeaders[i] = cgoHeader
|
p.cgoHeaders[i] = cgoHeader
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define CFlags that will be used while parsing the package.
|
// Define CFlags that will be used while parsing the package.
|
||||||
@@ -289,7 +294,7 @@ func Process(files []*ast.File, dir string, fset *token.FileSet, cflags []string
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve types such as C.int, C.longlong, etc from C.
|
// Retrieve types such as C.int, C.longlong, etc from C.
|
||||||
p.newCGoFile().readNames(builtinAliasTypedefs, cflagsForCGo, "", func(names map[string]clangCursor) {
|
p.newCGoFile(nil, -1).readNames(builtinAliasTypedefs, cflagsForCGo, "", func(names map[string]clangCursor) {
|
||||||
gen := &ast.GenDecl{
|
gen := &ast.GenDecl{
|
||||||
TokPos: token.NoPos,
|
TokPos: token.NoPos,
|
||||||
Tok: token.TYPE,
|
Tok: token.TYPE,
|
||||||
@@ -303,8 +308,8 @@ func Process(files []*ast.File, dir string, fset *token.FileSet, cflags []string
|
|||||||
|
|
||||||
// Process CGo imports for each file.
|
// Process CGo imports for each file.
|
||||||
for i, f := range files {
|
for i, f := range files {
|
||||||
cf := p.newCGoFile()
|
cf := p.newCGoFile(f, i)
|
||||||
cf.readNames(cgoHeaders[i], cflagsForCGo, filepath.Base(fset.File(f.Pos()).Name()), func(names map[string]clangCursor) {
|
cf.readNames(p.cgoHeaders[i], cflagsForCGo, filepath.Base(fset.File(f.Pos()).Name()), func(names map[string]clangCursor) {
|
||||||
for _, name := range builtinAliases {
|
for _, name := range builtinAliases {
|
||||||
// Names such as C.int should not be obtained from C.
|
// Names such as C.int should not be obtained from C.
|
||||||
// This works around an issue in picolibc that has `#define int`
|
// This works around an issue in picolibc that has `#define int`
|
||||||
@@ -320,12 +325,14 @@ func Process(files []*ast.File, dir string, fset *token.FileSet, cflags []string
|
|||||||
// Print the newly generated in-memory AST, for debugging.
|
// Print the newly generated in-memory AST, for debugging.
|
||||||
//ast.Print(fset, p.generated)
|
//ast.Print(fset, p.generated)
|
||||||
|
|
||||||
return p.generated, cgoHeaders, p.cflags, p.ldflags, p.visitedFiles, p.errors
|
return p.generated, p.cgoHeaders, p.cflags, p.ldflags, p.visitedFiles, p.errors
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *cgoPackage) newCGoFile() *cgoFile {
|
func (p *cgoPackage) newCGoFile(file *ast.File, index int) *cgoFile {
|
||||||
return &cgoFile{
|
return &cgoFile{
|
||||||
cgoPackage: p,
|
cgoPackage: p,
|
||||||
|
file: file,
|
||||||
|
index: index,
|
||||||
defined: make(map[string]ast.Node),
|
defined: make(map[string]ast.Node),
|
||||||
names: make(map[string]clangCursor),
|
names: make(map[string]clangCursor),
|
||||||
}
|
}
|
||||||
@@ -1117,8 +1124,11 @@ func (f *cgoFile) getASTDeclName(name string, found clangCursor, iscall bool) st
|
|||||||
return alias
|
return alias
|
||||||
}
|
}
|
||||||
node := f.getASTDeclNode(name, found, iscall)
|
node := f.getASTDeclNode(name, found, iscall)
|
||||||
if _, ok := node.(*ast.FuncDecl); ok && !iscall {
|
if node, ok := node.(*ast.FuncDecl); ok {
|
||||||
return "C." + name + "$funcaddr"
|
if !iscall {
|
||||||
|
return node.Name.Name + "$funcaddr"
|
||||||
|
}
|
||||||
|
return node.Name.Name
|
||||||
}
|
}
|
||||||
return "C." + name
|
return "C." + name
|
||||||
}
|
}
|
||||||
@@ -1142,7 +1152,7 @@ func (f *cgoFile) getASTDeclNode(name string, found clangCursor, iscall bool) as
|
|||||||
// Original cgo reports an error like
|
// Original cgo reports an error like
|
||||||
// cgo: inconsistent definitions for C.myint
|
// cgo: inconsistent definitions for C.myint
|
||||||
// which is far less helpful.
|
// which is far less helpful.
|
||||||
f.addError(getPos(node), "defined previously at "+f.fset.Position(getPos(newNode)).String()+" with a different type")
|
f.addError(getPos(node), name+" defined previously at "+f.fset.Position(getPos(newNode)).String()+" with a different type")
|
||||||
}
|
}
|
||||||
f.defined[name] = node
|
f.defined[name] = node
|
||||||
return node
|
return node
|
||||||
@@ -1150,11 +1160,39 @@ func (f *cgoFile) getASTDeclNode(name string, found clangCursor, iscall bool) as
|
|||||||
|
|
||||||
// The declaration has no AST node. Create it now.
|
// The declaration has no AST node. Create it now.
|
||||||
f.defined[name] = nil
|
f.defined[name] = nil
|
||||||
node, elaboratedType := f.createASTNode(name, found)
|
node, extra := f.createASTNode(name, found)
|
||||||
f.defined[name] = node
|
f.defined[name] = node
|
||||||
f.definedGlobally[name] = node
|
|
||||||
switch node := node.(type) {
|
switch node := node.(type) {
|
||||||
case *ast.FuncDecl:
|
case *ast.FuncDecl:
|
||||||
|
if strings.HasPrefix(node.Doc.List[0].Text, "//export _Cgo_static_") {
|
||||||
|
// Static function. Only accessible in the current Go file.
|
||||||
|
globalName := strings.TrimPrefix(node.Doc.List[0].Text, "//export ")
|
||||||
|
// Make an alias. Normally this is done using the alias function
|
||||||
|
// attribute, but MacOS for some reason doesn't support this (even
|
||||||
|
// though the linker has support for aliases in the form of N_INDR).
|
||||||
|
// Therefore, create an actual function for MacOS.
|
||||||
|
var params []string
|
||||||
|
for _, param := range node.Type.Params.List {
|
||||||
|
params = append(params, param.Names[0].Name)
|
||||||
|
}
|
||||||
|
callInst := fmt.Sprintf("%s(%s);", name, strings.Join(params, ", "))
|
||||||
|
if node.Type.Results != nil {
|
||||||
|
callInst = "return " + callInst
|
||||||
|
}
|
||||||
|
aliasDeclaration := fmt.Sprintf(`
|
||||||
|
#ifdef __APPLE__
|
||||||
|
%s {
|
||||||
|
%s
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
extern __typeof(%s) %s __attribute__((alias(%#v)));
|
||||||
|
#endif
|
||||||
|
`, extra.(string), callInst, name, globalName, name)
|
||||||
|
f.cgoHeaders[f.index] += "\n\n" + aliasDeclaration
|
||||||
|
} else {
|
||||||
|
// Regular (non-static) function.
|
||||||
|
f.definedGlobally[name] = node
|
||||||
|
}
|
||||||
f.generated.Decls = append(f.generated.Decls, node)
|
f.generated.Decls = append(f.generated.Decls, node)
|
||||||
// Also add a declaration like the following:
|
// Also add a declaration like the following:
|
||||||
// var C.foo$funcaddr unsafe.Pointer
|
// var C.foo$funcaddr unsafe.Pointer
|
||||||
@@ -1162,7 +1200,7 @@ func (f *cgoFile) getASTDeclNode(name string, found clangCursor, iscall bool) as
|
|||||||
Tok: token.VAR,
|
Tok: token.VAR,
|
||||||
Specs: []ast.Spec{
|
Specs: []ast.Spec{
|
||||||
&ast.ValueSpec{
|
&ast.ValueSpec{
|
||||||
Names: []*ast.Ident{{Name: "C." + name + "$funcaddr"}},
|
Names: []*ast.Ident{{Name: node.Name.Name + "$funcaddr"}},
|
||||||
Type: &ast.SelectorExpr{
|
Type: &ast.SelectorExpr{
|
||||||
X: &ast.Ident{Name: "unsafe"},
|
X: &ast.Ident{Name: "unsafe"},
|
||||||
Sel: &ast.Ident{Name: "Pointer"},
|
Sel: &ast.Ident{Name: "Pointer"},
|
||||||
@@ -1171,8 +1209,10 @@ func (f *cgoFile) getASTDeclNode(name string, found clangCursor, iscall bool) as
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
case *ast.GenDecl:
|
case *ast.GenDecl:
|
||||||
|
f.definedGlobally[name] = node
|
||||||
f.generated.Decls = append(f.generated.Decls, node)
|
f.generated.Decls = append(f.generated.Decls, node)
|
||||||
case *ast.TypeSpec:
|
case *ast.TypeSpec:
|
||||||
|
f.definedGlobally[name] = node
|
||||||
f.generated.Decls = append(f.generated.Decls, &ast.GenDecl{
|
f.generated.Decls = append(f.generated.Decls, &ast.GenDecl{
|
||||||
Tok: token.TYPE,
|
Tok: token.TYPE,
|
||||||
Specs: []ast.Spec{node},
|
Specs: []ast.Spec{node},
|
||||||
@@ -1186,7 +1226,8 @@ func (f *cgoFile) getASTDeclNode(name string, found clangCursor, iscall bool) as
|
|||||||
|
|
||||||
// If this is a struct or union it may need bitfields or union accessor
|
// If this is a struct or union it may need bitfields or union accessor
|
||||||
// methods.
|
// methods.
|
||||||
if elaboratedType != nil {
|
switch elaboratedType := extra.(type) {
|
||||||
|
case *elaboratedTypeInfo:
|
||||||
// Add struct bitfields.
|
// Add struct bitfields.
|
||||||
for _, bitfield := range elaboratedType.bitfields {
|
for _, bitfield := range elaboratedType.bitfields {
|
||||||
f.createBitfieldGetter(bitfield, "C."+name)
|
f.createBitfieldGetter(bitfield, "C."+name)
|
||||||
|
|||||||
+1
-1
@@ -48,7 +48,7 @@ func TestCGo(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Process the AST with CGo.
|
// Process the AST with CGo.
|
||||||
cgoAST, _, _, _, _, cgoErrors := Process([]*ast.File{f}, "testdata", fset, cflags, "")
|
cgoAST, _, _, _, _, cgoErrors := Process([]*ast.File{f}, "testdata", "main", fset, cflags, "")
|
||||||
|
|
||||||
// Check the AST for type errors.
|
// Check the AST for type errors.
|
||||||
var typecheckErrors []error
|
var typecheckErrors []error
|
||||||
|
|||||||
+33
-4
@@ -4,7 +4,9 @@ package cgo
|
|||||||
// modification. It does not touch the AST itself.
|
// modification. It does not touch the AST itself.
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/sha256"
|
||||||
"crypto/sha512"
|
"crypto/sha512"
|
||||||
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
"go/scanner"
|
"go/scanner"
|
||||||
@@ -43,6 +45,8 @@ typedef struct {
|
|||||||
GoCXCursor tinygo_clang_getTranslationUnitCursor(CXTranslationUnit tu);
|
GoCXCursor tinygo_clang_getTranslationUnitCursor(CXTranslationUnit tu);
|
||||||
unsigned tinygo_clang_visitChildren(GoCXCursor parent, CXCursorVisitor visitor, CXClientData client_data);
|
unsigned tinygo_clang_visitChildren(GoCXCursor parent, CXCursorVisitor visitor, CXClientData client_data);
|
||||||
CXString tinygo_clang_getCursorSpelling(GoCXCursor c);
|
CXString tinygo_clang_getCursorSpelling(GoCXCursor c);
|
||||||
|
CXString tinygo_clang_getCursorPrettyPrinted(GoCXCursor c, CXPrintingPolicy Policy);
|
||||||
|
CXPrintingPolicy tinygo_clang_getCursorPrintingPolicy(GoCXCursor c);
|
||||||
enum CXCursorKind tinygo_clang_getCursorKind(GoCXCursor c);
|
enum CXCursorKind tinygo_clang_getCursorKind(GoCXCursor c);
|
||||||
CXType tinygo_clang_getCursorType(GoCXCursor c);
|
CXType tinygo_clang_getCursorType(GoCXCursor c);
|
||||||
GoCXCursor tinygo_clang_getTypeDeclaration(CXType t);
|
GoCXCursor tinygo_clang_getTypeDeclaration(CXType t);
|
||||||
@@ -50,6 +54,7 @@ CXType tinygo_clang_getTypedefDeclUnderlyingType(GoCXCursor c);
|
|||||||
CXType tinygo_clang_getCursorResultType(GoCXCursor c);
|
CXType tinygo_clang_getCursorResultType(GoCXCursor c);
|
||||||
int tinygo_clang_Cursor_getNumArguments(GoCXCursor c);
|
int tinygo_clang_Cursor_getNumArguments(GoCXCursor c);
|
||||||
GoCXCursor tinygo_clang_Cursor_getArgument(GoCXCursor c, unsigned i);
|
GoCXCursor tinygo_clang_Cursor_getArgument(GoCXCursor c, unsigned i);
|
||||||
|
enum CX_StorageClass tinygo_clang_Cursor_getStorageClass(GoCXCursor c);
|
||||||
CXSourceLocation tinygo_clang_getCursorLocation(GoCXCursor c);
|
CXSourceLocation tinygo_clang_getCursorLocation(GoCXCursor c);
|
||||||
CXSourceRange tinygo_clang_getCursorExtent(GoCXCursor c);
|
CXSourceRange tinygo_clang_getCursorExtent(GoCXCursor c);
|
||||||
CXTranslationUnit tinygo_clang_Cursor_getTranslationUnit(GoCXCursor c);
|
CXTranslationUnit tinygo_clang_Cursor_getTranslationUnit(GoCXCursor c);
|
||||||
@@ -189,7 +194,7 @@ func (f *cgoFile) readNames(fragment string, cflags []string, filename string, c
|
|||||||
|
|
||||||
// Convert the AST node under the given Clang cursor to a Go AST node and return
|
// Convert the AST node under the given Clang cursor to a Go AST node and return
|
||||||
// it.
|
// it.
|
||||||
func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, *elaboratedTypeInfo) {
|
func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) {
|
||||||
kind := C.tinygo_clang_getCursorKind(c)
|
kind := C.tinygo_clang_getCursorKind(c)
|
||||||
pos := f.getCursorPosition(c)
|
pos := f.getCursorPosition(c)
|
||||||
switch kind {
|
switch kind {
|
||||||
@@ -200,19 +205,43 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, *elaborat
|
|||||||
Kind: ast.Fun,
|
Kind: ast.Fun,
|
||||||
Name: "C." + name,
|
Name: "C." + name,
|
||||||
}
|
}
|
||||||
|
exportName := name
|
||||||
|
localName := name
|
||||||
|
var stringSignature string
|
||||||
|
if C.tinygo_clang_Cursor_getStorageClass(c) == C.CX_SC_Static {
|
||||||
|
// A static function is assigned a globally unique symbol name based
|
||||||
|
// on the file path (like _Cgo_static_2d09198adbf58f4f4655_foo) and
|
||||||
|
// has a different Go name in the form of C.foo!symbols.go instead
|
||||||
|
// of just C.foo.
|
||||||
|
path := f.importPath + "/" + filepath.Base(f.fset.File(f.file.Pos()).Name())
|
||||||
|
staticIDBuf := sha256.Sum256([]byte(path))
|
||||||
|
staticID := hex.EncodeToString(staticIDBuf[:10])
|
||||||
|
exportName = "_Cgo_static_" + staticID + "_" + name
|
||||||
|
localName = name + "!" + filepath.Base(path)
|
||||||
|
|
||||||
|
// Create a signature. This is necessary for MacOS to forward the
|
||||||
|
// call, because MacOS doesn't support aliases like ELF and PE do.
|
||||||
|
// (There is N_INDR but __attribute__((alias("..."))) doesn't work).
|
||||||
|
policy := C.tinygo_clang_getCursorPrintingPolicy(c)
|
||||||
|
defer C.clang_PrintingPolicy_dispose(policy)
|
||||||
|
C.clang_PrintingPolicy_setProperty(policy, C.CXPrintingPolicy_TerseOutput, 1)
|
||||||
|
stringSignature = getString(C.tinygo_clang_getCursorPrettyPrinted(c, policy))
|
||||||
|
stringSignature = strings.Replace(stringSignature, " "+name+"(", " "+exportName+"(", 1)
|
||||||
|
stringSignature = strings.TrimPrefix(stringSignature, "static ")
|
||||||
|
}
|
||||||
args := make([]*ast.Field, numArgs)
|
args := make([]*ast.Field, numArgs)
|
||||||
decl := &ast.FuncDecl{
|
decl := &ast.FuncDecl{
|
||||||
Doc: &ast.CommentGroup{
|
Doc: &ast.CommentGroup{
|
||||||
List: []*ast.Comment{
|
List: []*ast.Comment{
|
||||||
{
|
{
|
||||||
Slash: pos - 1,
|
Slash: pos - 1,
|
||||||
Text: "//export " + name,
|
Text: "//export " + exportName,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Name: &ast.Ident{
|
Name: &ast.Ident{
|
||||||
NamePos: pos,
|
NamePos: pos,
|
||||||
Name: "C." + name,
|
Name: "C." + localName,
|
||||||
Obj: obj,
|
Obj: obj,
|
||||||
},
|
},
|
||||||
Type: &ast.FuncType{
|
Type: &ast.FuncType{
|
||||||
@@ -263,7 +292,7 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, *elaborat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
obj.Decl = decl
|
obj.Decl = decl
|
||||||
return decl, nil
|
return decl, stringSignature
|
||||||
case C.CXCursor_StructDecl, C.CXCursor_UnionDecl:
|
case C.CXCursor_StructDecl, C.CXCursor_UnionDecl:
|
||||||
typ := f.makeASTRecordType(c, pos)
|
typ := f.makeASTRecordType(c, pos)
|
||||||
typeName := "C." + name
|
typeName := "C." + name
|
||||||
|
|||||||
@@ -17,6 +17,14 @@ CXString tinygo_clang_getCursorSpelling(CXCursor c) {
|
|||||||
return clang_getCursorSpelling(c);
|
return clang_getCursorSpelling(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CXString tinygo_clang_getCursorPrettyPrinted(CXCursor c, CXPrintingPolicy policy) {
|
||||||
|
return clang_getCursorPrettyPrinted(c, policy);
|
||||||
|
}
|
||||||
|
|
||||||
|
CXPrintingPolicy tinygo_clang_getCursorPrintingPolicy(CXCursor c) {
|
||||||
|
return clang_getCursorPrintingPolicy(c);
|
||||||
|
}
|
||||||
|
|
||||||
enum CXCursorKind tinygo_clang_getCursorKind(CXCursor c) {
|
enum CXCursorKind tinygo_clang_getCursorKind(CXCursor c) {
|
||||||
return clang_getCursorKind(c);
|
return clang_getCursorKind(c);
|
||||||
}
|
}
|
||||||
@@ -45,6 +53,10 @@ CXCursor tinygo_clang_Cursor_getArgument(CXCursor c, unsigned i) {
|
|||||||
return clang_Cursor_getArgument(c, i);
|
return clang_Cursor_getArgument(c, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum CX_StorageClass tinygo_clang_Cursor_getStorageClass(CXCursor c) {
|
||||||
|
return clang_Cursor_getStorageClass(c);
|
||||||
|
}
|
||||||
|
|
||||||
CXSourceLocation tinygo_clang_getCursorLocation(CXCursor c) {
|
CXSourceLocation tinygo_clang_getCursorLocation(CXCursor c) {
|
||||||
return clang_getCursorLocation(c);
|
return clang_getCursorLocation(c);
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+2
@@ -5,6 +5,7 @@ package main
|
|||||||
int foo(int a, int b);
|
int foo(int a, int b);
|
||||||
void variadic0();
|
void variadic0();
|
||||||
void variadic2(int x, int y, ...);
|
void variadic2(int x, int y, ...);
|
||||||
|
static void staticfunc(int x);
|
||||||
|
|
||||||
// Global variable signatures.
|
// Global variable signatures.
|
||||||
extern int someValue;
|
extern int someValue;
|
||||||
@@ -16,6 +17,7 @@ func accessFunctions() {
|
|||||||
C.foo(3, 4)
|
C.foo(3, 4)
|
||||||
C.variadic0()
|
C.variadic0()
|
||||||
C.variadic2(3, 5)
|
C.variadic2(3, 5)
|
||||||
|
C.staticfunc(3)
|
||||||
}
|
}
|
||||||
|
|
||||||
func accessGlobals() {
|
func accessGlobals() {
|
||||||
|
|||||||
Vendored
+5
@@ -55,5 +55,10 @@ func C.variadic2(x C.int, y C.int)
|
|||||||
|
|
||||||
var C.variadic2$funcaddr unsafe.Pointer
|
var C.variadic2$funcaddr unsafe.Pointer
|
||||||
|
|
||||||
|
//export _Cgo_static_173c95a79b6df1980521_staticfunc
|
||||||
|
func C.staticfunc!symbols.go(x C.int)
|
||||||
|
|
||||||
|
var C.staticfunc!symbols.go$funcaddr unsafe.Pointer
|
||||||
|
|
||||||
//go:extern someValue
|
//go:extern someValue
|
||||||
var C.someValue C.int
|
var C.someValue C.int
|
||||||
|
|||||||
@@ -175,6 +175,15 @@ func (c *Config) AutomaticStackSize() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StackSize returns the default stack size to be used for goroutines, if the
|
||||||
|
// stack size could not be determined automatically at compile time.
|
||||||
|
func (c *Config) StackSize() uint64 {
|
||||||
|
if c.Options.StackSize != 0 {
|
||||||
|
return c.Options.StackSize
|
||||||
|
}
|
||||||
|
return c.Target.DefaultStackSize
|
||||||
|
}
|
||||||
|
|
||||||
// UseThinLTO returns whether ThinLTO should be used for the given target. Some
|
// UseThinLTO returns whether ThinLTO should be used for the given target. Some
|
||||||
// targets (such as wasm) are not yet supported.
|
// targets (such as wasm) are not yet supported.
|
||||||
// We should try and remove as many exceptions as possible in the future, so
|
// We should try and remove as many exceptions as possible in the future, so
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ type Options struct {
|
|||||||
GC string
|
GC string
|
||||||
PanicStrategy string
|
PanicStrategy string
|
||||||
Scheduler string
|
Scheduler string
|
||||||
|
StackSize uint64 // goroutine stack size (if none could be automatically determined)
|
||||||
Serial string
|
Serial string
|
||||||
Work bool // -work flag to print temporary build directory
|
Work bool // -work flag to print temporary build directory
|
||||||
InterpTimeout time.Duration
|
InterpTimeout time.Duration
|
||||||
@@ -49,6 +50,8 @@ type Options struct {
|
|||||||
LLVMFeatures string
|
LLVMFeatures string
|
||||||
Directory string
|
Directory string
|
||||||
PrintJSON bool
|
PrintJSON bool
|
||||||
|
Monitor bool
|
||||||
|
BaudRate int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify performs a validation on the given options, raising an error if options are not valid.
|
// Verify performs a validation on the given options, raising an error if options are not valid.
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ func TestCompiler(t *testing.T) {
|
|||||||
RelocationModel: config.RelocationModel(),
|
RelocationModel: config.RelocationModel(),
|
||||||
Scheduler: config.Scheduler(),
|
Scheduler: config.Scheduler(),
|
||||||
AutomaticStackSize: config.AutomaticStackSize(),
|
AutomaticStackSize: config.AutomaticStackSize(),
|
||||||
DefaultStackSize: config.Target.DefaultStackSize,
|
DefaultStackSize: config.StackSize(),
|
||||||
NeedsStackObjects: config.NeedsStackObjects(),
|
NeedsStackObjects: config.NeedsStackObjects(),
|
||||||
}
|
}
|
||||||
machine, err := NewTargetMachine(compilerConfig)
|
machine, err := NewTargetMachine(compilerConfig)
|
||||||
|
|||||||
@@ -9,8 +9,10 @@ require (
|
|||||||
github.com/chromedp/chromedp v0.7.6
|
github.com/chromedp/chromedp v0.7.6
|
||||||
github.com/gofrs/flock v0.8.1
|
github.com/gofrs/flock v0.8.1
|
||||||
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf
|
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf
|
||||||
|
github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf
|
||||||
github.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892
|
github.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892
|
||||||
github.com/mattn/go-colorable v0.1.8
|
github.com/mattn/go-colorable v0.1.8
|
||||||
|
github.com/mattn/go-tty v0.0.4
|
||||||
go.bug.st/serial v1.3.5
|
go.bug.st/serial v1.3.5
|
||||||
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261
|
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261
|
||||||
golang.org/x/tools v0.1.11
|
golang.org/x/tools v0.1.11
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moA
|
|||||||
github.com/creack/goselect v0.1.2 h1:2DNy14+JPjRBgPzAd1thbQp4BSIihxcBf0IXhQXDRa0=
|
github.com/creack/goselect v0.1.2 h1:2DNy14+JPjRBgPzAd1thbQp4BSIihxcBf0IXhQXDRa0=
|
||||||
github.com/creack/goselect v0.1.2/go.mod h1:a/NhLweNvqIYMuxcMOuWY516Cimucms3DglDzQP3hKY=
|
github.com/creack/goselect v0.1.2/go.mod h1:a/NhLweNvqIYMuxcMOuWY516Cimucms3DglDzQP3hKY=
|
||||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
|
github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
|
||||||
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
|
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
|
||||||
github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
|
github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
|
||||||
@@ -23,44 +22,47 @@ github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
|
|||||||
github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
|
github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
|
||||||
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf h1:7+FW5aGwISbqUtkfmIpZJGRgNFg2ioYPvFaUxdqpDsg=
|
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf h1:7+FW5aGwISbqUtkfmIpZJGRgNFg2ioYPvFaUxdqpDsg=
|
||||||
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf/go.mod h1:RpwtwJQFrIEPstU94h88MWPXP2ektJZ8cZ0YntAmXiE=
|
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf/go.mod h1:RpwtwJQFrIEPstU94h88MWPXP2ektJZ8cZ0YntAmXiE=
|
||||||
|
github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf h1:FtEj8sfIcaaBfAKrE1Cwb61YDtYq9JxChK1c7AKce7s=
|
||||||
|
github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf/go.mod h1:yrqSXGoD/4EKfF26AOGzscPOgTTJcyAwM2rpixWT+t4=
|
||||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||||
github.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892 h1:6J+qramlHVLmiBOgRiBOnQkno8uprqG6YFFQTt6uYIw=
|
github.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892 h1:6J+qramlHVLmiBOgRiBOnQkno8uprqG6YFFQTt6uYIw=
|
||||||
github.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892/go.mod h1:Pb6XcsXyropB9LNHhnqaknG/vEwYztLkQzVCHv8sQ3M=
|
github.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892/go.mod h1:Pb6XcsXyropB9LNHhnqaknG/vEwYztLkQzVCHv8sQ3M=
|
||||||
|
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||||
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
|
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
|
||||||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||||
|
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||||
|
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
||||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
|
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||||
|
github.com/mattn/go-tty v0.0.4 h1:NVikla9X8MN0SQAqCYzpGyXv0jY7MNl3HOWD2dkle7E=
|
||||||
|
github.com/mattn/go-tty v0.0.4/go.mod h1:u5GGXBtZU6RQoKV8gY5W6UhMudbR5vXnUe7j3pxse28=
|
||||||
github.com/orisano/pixelmatch v0.0.0-20210112091706-4fa4c7ba91d5 h1:1SoBaSPudixRecmlHXb/GxmaD3fLMtHIDN13QujwQuc=
|
github.com/orisano/pixelmatch v0.0.0-20210112091706-4fa4c7ba91d5 h1:1SoBaSPudixRecmlHXb/GxmaD3fLMtHIDN13QujwQuc=
|
||||||
github.com/orisano/pixelmatch v0.0.0-20210112091706-4fa4c7ba91d5/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
|
github.com/orisano/pixelmatch v0.0.0-20210112091706-4fa4c7ba91d5/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
|
||||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
|
||||||
go.bug.st/serial v1.1.3 h1:YEBxJa9pKS9Wdg46B/jiaKbvvbUrjhZZZITfJHEJhaE=
|
|
||||||
go.bug.st/serial v1.1.3/go.mod h1:8TT7u/SwwNIpJ8QaG4s+HTjFt9ReXs2cdOU7ZEk50Dk=
|
|
||||||
go.bug.st/serial v1.3.5 h1:k50SqGZCnHZ2MiBQgzccXWG+kd/XpOs1jUljpDDKzaE=
|
go.bug.st/serial v1.3.5 h1:k50SqGZCnHZ2MiBQgzccXWG+kd/XpOs1jUljpDDKzaE=
|
||||||
go.bug.st/serial v1.3.5/go.mod h1:z8CesKorE90Qr/oRSJiEuvzYRKol9r/anJZEb5kt304=
|
go.bug.st/serial v1.3.5/go.mod h1:z8CesKorE90Qr/oRSJiEuvzYRKol9r/anJZEb5kt304=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
|
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0=
|
|
||||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 h1:v6hYoSR9T5oet+pMXwUWkbiVqx/63mlHjefrHmxwfeY=
|
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 h1:v6hYoSR9T5oet+pMXwUWkbiVqx/63mlHjefrHmxwfeY=
|
||||||
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/tools v0.1.11 h1:loJ25fNOEhSXfHrpoGj91eCUThwdNX6u24rO1xnNteY=
|
golang.org/x/tools v0.1.11 h1:loJ25fNOEhSXfHrpoGj91eCUThwdNX6u24rO1xnNteY=
|
||||||
golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4=
|
golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
||||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||||
tinygo.org/x/go-llvm v0.0.0-20220802112859-5bb0b77907a7 h1:nSLR52mUw7DPQQVA3ZJFH63zjU4ME84fKiin6mdnYWc=
|
tinygo.org/x/go-llvm v0.0.0-20220802112859-5bb0b77907a7 h1:nSLR52mUw7DPQQVA3ZJFH63zjU4ME84fKiin6mdnYWc=
|
||||||
tinygo.org/x/go-llvm v0.0.0-20220802112859-5bb0b77907a7/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
|
tinygo.org/x/go-llvm v0.0.0-20220802112859-5bb0b77907a7/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
|
||||||
|
|||||||
@@ -369,6 +369,11 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent
|
|||||||
nBytes := uint32(operands[3].Uint())
|
nBytes := uint32(operands[3].Uint())
|
||||||
dstObj := mem.getWritable(dst.index())
|
dstObj := mem.getWritable(dst.index())
|
||||||
dstBuf := dstObj.buffer.asRawValue(r)
|
dstBuf := dstObj.buffer.asRawValue(r)
|
||||||
|
if mem.get(src.index()).buffer == nil {
|
||||||
|
// Looks like the source buffer is not defined.
|
||||||
|
// This can happen with //extern or //go:embed.
|
||||||
|
return nil, mem, r.errorAt(inst, errUnsupportedRuntimeInst)
|
||||||
|
}
|
||||||
srcBuf := mem.get(src.index()).buffer.asRawValue(r)
|
srcBuf := mem.get(src.index()).buffer.asRawValue(r)
|
||||||
copy(dstBuf.buf[dst.offset():dst.offset()+nBytes], srcBuf.buf[src.offset():])
|
copy(dstBuf.buf[dst.offset():dst.offset()+nBytes], srcBuf.buf[src.offset():])
|
||||||
dstObj.buffer = dstBuf
|
dstObj.buffer = dstBuf
|
||||||
|
|||||||
+1
-1
@@ -440,7 +440,7 @@ func (p *Package) parseFiles() ([]*ast.File, error) {
|
|||||||
var initialCFlags []string
|
var initialCFlags []string
|
||||||
initialCFlags = append(initialCFlags, p.program.config.CFlags()...)
|
initialCFlags = append(initialCFlags, p.program.config.CFlags()...)
|
||||||
initialCFlags = append(initialCFlags, "-I"+p.Dir)
|
initialCFlags = append(initialCFlags, "-I"+p.Dir)
|
||||||
generated, headerCode, cflags, ldflags, accessedFiles, errs := cgo.Process(files, p.program.workingDir, p.program.fset, initialCFlags, p.program.clangHeaders)
|
generated, headerCode, cflags, ldflags, accessedFiles, errs := cgo.Process(files, p.program.workingDir, p.ImportPath, p.program.fset, initialCFlags, p.program.clangHeaders)
|
||||||
p.CFlags = append(initialCFlags, cflags...)
|
p.CFlags = append(initialCFlags, cflags...)
|
||||||
p.CGoHeaders = headerCode
|
p.CGoHeaders = headerCode
|
||||||
for path, hash := range accessedFiles {
|
for path, hash := range accessedFiles {
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/shlex"
|
"github.com/google/shlex"
|
||||||
|
"github.com/inhies/go-bytesize"
|
||||||
"github.com/mattn/go-colorable"
|
"github.com/mattn/go-colorable"
|
||||||
"github.com/tinygo-org/tinygo/builder"
|
"github.com/tinygo-org/tinygo/builder"
|
||||||
"github.com/tinygo-org/tinygo/compileopts"
|
"github.com/tinygo-org/tinygo/compileopts"
|
||||||
@@ -422,7 +423,6 @@ func Flash(pkgName, port string, options *compileopts.Options) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return &commandError{"failed to flash", result.Binary, err}
|
return &commandError{"failed to flash", result.Binary, err}
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
case "msd":
|
case "msd":
|
||||||
switch fileExt {
|
switch fileExt {
|
||||||
case ".uf2":
|
case ".uf2":
|
||||||
@@ -430,13 +430,11 @@ func Flash(pkgName, port string, options *compileopts.Options) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return &commandError{"failed to flash", result.Binary, err}
|
return &commandError{"failed to flash", result.Binary, err}
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
case ".hex":
|
case ".hex":
|
||||||
err := flashHexUsingMSD(config.Target.FlashVolume, result.Binary, config.Options)
|
err := flashHexUsingMSD(config.Target.FlashVolume, result.Binary, config.Options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &commandError{"failed to flash", result.Binary, err}
|
return &commandError{"failed to flash", result.Binary, err}
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
default:
|
default:
|
||||||
return errors.New("mass storage device flashing currently only supports uf2 and hex")
|
return errors.New("mass storage device flashing currently only supports uf2 and hex")
|
||||||
}
|
}
|
||||||
@@ -457,7 +455,6 @@ func Flash(pkgName, port string, options *compileopts.Options) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return &commandError{"failed to flash", result.Binary, err}
|
return &commandError{"failed to flash", result.Binary, err}
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
case "bmp":
|
case "bmp":
|
||||||
gdb, err := config.Target.LookupGDB()
|
gdb, err := config.Target.LookupGDB()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -476,10 +473,13 @@ func Flash(pkgName, port string, options *compileopts.Options) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return &commandError{"failed to flash", result.Binary, err}
|
return &commandError{"failed to flash", result.Binary, err}
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unknown flash method: %s", flashMethod)
|
return fmt.Errorf("unknown flash method: %s", flashMethod)
|
||||||
}
|
}
|
||||||
|
if options.Monitor {
|
||||||
|
return Monitor("", options)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -998,7 +998,8 @@ func getDefaultPort(portFlag string, usbInterfaces []string) (port string, err e
|
|||||||
preferredPortIDs = append(preferredPortIDs, [2]uint16{uint16(vid), uint16(pid)})
|
preferredPortIDs = append(preferredPortIDs, [2]uint16{uint16(vid), uint16(pid)})
|
||||||
}
|
}
|
||||||
|
|
||||||
var primaryPorts []string // ports picked from preferred USB VID/PID
|
var primaryPorts []string // ports picked from preferred USB VID/PID
|
||||||
|
var secondaryPorts []string // other ports (as a fallback)
|
||||||
for _, p := range portsList {
|
for _, p := range portsList {
|
||||||
if !p.IsUSB {
|
if !p.IsUSB {
|
||||||
continue
|
continue
|
||||||
@@ -1020,6 +1021,8 @@ func getDefaultPort(portFlag string, usbInterfaces []string) (port string, err e
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
secondaryPorts = append(secondaryPorts, p.Name)
|
||||||
}
|
}
|
||||||
if len(primaryPorts) == 1 {
|
if len(primaryPorts) == 1 {
|
||||||
// There is exactly one match in the set of preferred ports. Use
|
// There is exactly one match in the set of preferred ports. Use
|
||||||
@@ -1031,18 +1034,10 @@ func getDefaultPort(portFlag string, usbInterfaces []string) (port string, err e
|
|||||||
// one device of the same type are connected (e.g. two Arduino
|
// one device of the same type are connected (e.g. two Arduino
|
||||||
// Unos).
|
// Unos).
|
||||||
ports = primaryPorts
|
ports = primaryPorts
|
||||||
}
|
} else {
|
||||||
|
// No preferred ports found. Fall back to other serial ports
|
||||||
if len(ports) == 0 {
|
// available in the system.
|
||||||
// fallback
|
ports = secondaryPorts
|
||||||
switch runtime.GOOS {
|
|
||||||
case "darwin":
|
|
||||||
ports, err = filepath.Glob("/dev/cu.usb*")
|
|
||||||
case "linux":
|
|
||||||
ports, err = filepath.Glob("/dev/ttyACM*")
|
|
||||||
case "windows":
|
|
||||||
ports, err = serial.GetPortsList()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return "", errors.New("unable to search for a default USB device to be flashed on this OS")
|
return "", errors.New("unable to search for a default USB device to be flashed on this OS")
|
||||||
@@ -1057,7 +1052,9 @@ func getDefaultPort(portFlag string, usbInterfaces []string) (port string, err e
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(portCandidates) == 0 {
|
if len(portCandidates) == 0 {
|
||||||
if len(ports) == 1 {
|
if len(usbInterfaces) > 0 {
|
||||||
|
return "", errors.New("unable to search for a default USB device - use -port flag, available ports are " + strings.Join(ports, ", "))
|
||||||
|
} else if len(ports) == 1 {
|
||||||
return ports[0], nil
|
return ports[0], nil
|
||||||
} else {
|
} else {
|
||||||
return "", errors.New("multiple serial ports available - use -port flag, available ports are " + strings.Join(ports, ", "))
|
return "", errors.New("multiple serial ports available - use -port flag, available ports are " + strings.Join(ports, ", "))
|
||||||
@@ -1122,6 +1119,7 @@ func usage(command string) {
|
|||||||
fmt.Fprintln(os.Stderr, " flash: compile and flash to the device")
|
fmt.Fprintln(os.Stderr, " flash: compile and flash to the device")
|
||||||
fmt.Fprintln(os.Stderr, " gdb: run/flash and immediately enter GDB")
|
fmt.Fprintln(os.Stderr, " gdb: run/flash and immediately enter GDB")
|
||||||
fmt.Fprintln(os.Stderr, " lldb: run/flash and immediately enter LLDB")
|
fmt.Fprintln(os.Stderr, " lldb: run/flash and immediately enter LLDB")
|
||||||
|
fmt.Fprintln(os.Stderr, " monitor: open communication port")
|
||||||
fmt.Fprintln(os.Stderr, " env: list environment variables used during build")
|
fmt.Fprintln(os.Stderr, " env: list environment variables used during build")
|
||||||
fmt.Fprintln(os.Stderr, " list: run go list using the TinyGo root")
|
fmt.Fprintln(os.Stderr, " list: run go list using the TinyGo root")
|
||||||
fmt.Fprintln(os.Stderr, " clean: empty cache directory ("+goenv.Get("GOCACHE")+")")
|
fmt.Fprintln(os.Stderr, " clean: empty cache directory ("+goenv.Get("GOCACHE")+")")
|
||||||
@@ -1318,6 +1316,12 @@ func main() {
|
|||||||
var tags buildutil.TagsFlag
|
var tags buildutil.TagsFlag
|
||||||
flag.Var(&tags, "tags", "a space-separated list of extra build tags")
|
flag.Var(&tags, "tags", "a space-separated list of extra build tags")
|
||||||
target := flag.String("target", "", "chip/board name or JSON target specification file")
|
target := flag.String("target", "", "chip/board name or JSON target specification file")
|
||||||
|
var stackSize uint64
|
||||||
|
flag.Func("stack-size", "goroutine stack size (if unknown at compile time)", func(s string) error {
|
||||||
|
size, err := bytesize.Parse(s)
|
||||||
|
stackSize = uint64(size)
|
||||||
|
return err
|
||||||
|
})
|
||||||
printSize := flag.String("size", "", "print sizes (none, short, full)")
|
printSize := flag.String("size", "", "print sizes (none, short, full)")
|
||||||
printStacks := flag.Bool("print-stacks", false, "print stack sizes of goroutines")
|
printStacks := flag.Bool("print-stacks", false, "print stack sizes of goroutines")
|
||||||
printAllocsString := flag.String("print-allocs", "", "regular expression of functions for which heap allocations should be printed")
|
printAllocsString := flag.String("print-allocs", "", "regular expression of functions for which heap allocations should be printed")
|
||||||
@@ -1332,6 +1336,8 @@ func main() {
|
|||||||
wasmAbi := flag.String("wasm-abi", "", "WebAssembly ABI conventions: js (no i64 params) or generic")
|
wasmAbi := flag.String("wasm-abi", "", "WebAssembly ABI conventions: js (no i64 params) or generic")
|
||||||
llvmFeatures := flag.String("llvm-features", "", "comma separated LLVM features to enable")
|
llvmFeatures := flag.String("llvm-features", "", "comma separated LLVM features to enable")
|
||||||
cpuprofile := flag.String("cpuprofile", "", "cpuprofile output")
|
cpuprofile := flag.String("cpuprofile", "", "cpuprofile output")
|
||||||
|
monitor := flag.Bool("monitor", false, "enable serial monitor")
|
||||||
|
baudrate := flag.Int("baudrate", 115200, "baudrate of serial monitor")
|
||||||
|
|
||||||
var flagJSON, flagDeps, flagTest bool
|
var flagJSON, flagDeps, flagTest bool
|
||||||
if command == "help" || command == "list" || command == "info" || command == "build" {
|
if command == "help" || command == "list" || command == "info" || command == "build" {
|
||||||
@@ -1398,6 +1404,7 @@ func main() {
|
|||||||
GOARCH: goenv.Get("GOARCH"),
|
GOARCH: goenv.Get("GOARCH"),
|
||||||
GOARM: goenv.Get("GOARM"),
|
GOARM: goenv.Get("GOARM"),
|
||||||
Target: *target,
|
Target: *target,
|
||||||
|
StackSize: stackSize,
|
||||||
Opt: *opt,
|
Opt: *opt,
|
||||||
GC: *gc,
|
GC: *gc,
|
||||||
PanicStrategy: *panicStrategy,
|
PanicStrategy: *panicStrategy,
|
||||||
@@ -1420,6 +1427,8 @@ func main() {
|
|||||||
OpenOCDCommands: ocdCommands,
|
OpenOCDCommands: ocdCommands,
|
||||||
LLVMFeatures: *llvmFeatures,
|
LLVMFeatures: *llvmFeatures,
|
||||||
PrintJSON: flagJSON,
|
PrintJSON: flagJSON,
|
||||||
|
Monitor: *monitor,
|
||||||
|
BaudRate: *baudrate,
|
||||||
}
|
}
|
||||||
if *printCommands {
|
if *printCommands {
|
||||||
options.PrintCommands = printCommand
|
options.PrintCommands = printCommand
|
||||||
@@ -1610,6 +1619,9 @@ func main() {
|
|||||||
fmt.Println("FAIL")
|
fmt.Println("FAIL")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
case "monitor":
|
||||||
|
err := Monitor(*port, options)
|
||||||
|
handleCompilerError(err)
|
||||||
case "targets":
|
case "targets":
|
||||||
dir := filepath.Join(goenv.Get("TINYGOROOT"), "targets")
|
dir := filepath.Join(goenv.Get("TINYGOROOT"), "targets")
|
||||||
entries, err := ioutil.ReadDir(dir)
|
entries, err := ioutil.ReadDir(dir)
|
||||||
|
|||||||
+106
@@ -0,0 +1,106 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/mattn/go-tty"
|
||||||
|
"github.com/tinygo-org/tinygo/builder"
|
||||||
|
"github.com/tinygo-org/tinygo/compileopts"
|
||||||
|
"go.bug.st/serial"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Monitor connects to the given port and reads/writes the serial port.
|
||||||
|
func Monitor(port string, options *compileopts.Options) error {
|
||||||
|
config, err := builder.NewConfig(options)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
wait := 300
|
||||||
|
for i := 0; i <= wait; i++ {
|
||||||
|
port, err = getDefaultPort(port, config.Target.SerialPort)
|
||||||
|
if err != nil {
|
||||||
|
if i < wait {
|
||||||
|
time.Sleep(10 * time.Millisecond)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
br := options.BaudRate
|
||||||
|
if br <= 0 {
|
||||||
|
br = 115200
|
||||||
|
}
|
||||||
|
|
||||||
|
wait = 300
|
||||||
|
var p serial.Port
|
||||||
|
for i := 0; i <= wait; i++ {
|
||||||
|
p, err = serial.Open(port, &serial.Mode{BaudRate: br})
|
||||||
|
if err != nil {
|
||||||
|
if i < wait {
|
||||||
|
time.Sleep(10 * time.Millisecond)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
defer p.Close()
|
||||||
|
|
||||||
|
tty, err := tty.Open()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer tty.Close()
|
||||||
|
|
||||||
|
sig := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(sig, os.Interrupt)
|
||||||
|
defer signal.Stop(sig)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
<-sig
|
||||||
|
tty.Close()
|
||||||
|
os.Exit(0)
|
||||||
|
}()
|
||||||
|
|
||||||
|
fmt.Printf("Connected to %s. Press Ctrl-C to exit.\n", port)
|
||||||
|
|
||||||
|
errCh := make(chan error, 1)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
buf := make([]byte, 100*1024)
|
||||||
|
for {
|
||||||
|
n, err := p.Read(buf)
|
||||||
|
if err != nil {
|
||||||
|
errCh <- fmt.Errorf("read error: %w", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if n == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fmt.Printf("%v", string(buf[:n]))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
r, err := tty.ReadRune()
|
||||||
|
if err != nil {
|
||||||
|
errCh <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if r == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
p.Write([]byte(string(r)))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return <-errCh
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
//go:build nrf52840 || stm32 || (sam && atsamd51) || (sam && atsame5x) || rp2040
|
//go:build nrf || stm32 || (sam && atsamd51) || (sam && atsame5x)
|
||||||
// +build nrf52840 stm32 sam,atsamd51 sam,atsame5x rp2040
|
// +build nrf stm32 sam,atsamd51 sam,atsame5x
|
||||||
|
|
||||||
package rand
|
package rand
|
||||||
|
|
||||||
|
|||||||
@@ -1,49 +0,0 @@
|
|||||||
// Reads multiple rp2040 ADC channels concurrently. Including the internal temperature sensor
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"machine"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
type celsius float32
|
|
||||||
|
|
||||||
func (c celsius) String() string {
|
|
||||||
return fmt.Sprintf("%4.1f℃", c)
|
|
||||||
}
|
|
||||||
|
|
||||||
// rp2040 ADC is 12 bits. Reading are shifted <<4 to fill the 16-bit range.
|
|
||||||
var adcReading [3]uint16
|
|
||||||
|
|
||||||
func readADC(a machine.ADC, w time.Duration, i int) {
|
|
||||||
for {
|
|
||||||
adcReading[i] = a.Get()
|
|
||||||
time.Sleep(w)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
machine.InitADC()
|
|
||||||
a0 := machine.ADC{machine.ADC0} // GPIO26 input
|
|
||||||
a1 := machine.ADC{machine.ADC1} // GPIO27 input
|
|
||||||
a2 := machine.ADC{machine.ADC2} // GPIO28 input
|
|
||||||
t := machine.ADC_TEMP_SENSOR // Internal Temperature sensor
|
|
||||||
// Configure sets the GPIOs to PinAnalog mode
|
|
||||||
a0.Configure(machine.ADCConfig{})
|
|
||||||
a1.Configure(machine.ADCConfig{})
|
|
||||||
a2.Configure(machine.ADCConfig{})
|
|
||||||
// Configure powers on the temperature sensor
|
|
||||||
t.Configure(machine.ADCConfig{})
|
|
||||||
|
|
||||||
// Safe to read concurrently
|
|
||||||
go readADC(a0, 10*time.Millisecond, 0)
|
|
||||||
go readADC(a1, 17*time.Millisecond, 1)
|
|
||||||
go readADC(a2, 29*time.Millisecond, 2)
|
|
||||||
|
|
||||||
for {
|
|
||||||
fmt.Printf("ADC0: %5d ADC1: %5d ADC2: %5d Temp: %v\n\r", adcReading[0], adcReading[1], adcReading[2], celsius(float32(t.ReadTemperature())/1000))
|
|
||||||
time.Sleep(1000 * time.Millisecond)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
// Read the internal temperature sensor of the chip.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"machine"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type celsius float32
|
||||||
|
|
||||||
|
func (c celsius) String() string {
|
||||||
|
return fmt.Sprintf("%4.1f℃", c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
for {
|
||||||
|
temp := celsius(float32(machine.ReadTemperature()) / 1000)
|
||||||
|
println("temperature:", temp.String())
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
package machine
|
package machine
|
||||||
|
|
||||||
// used to reset into bootloader
|
// used to reset into bootloader
|
||||||
const RESET_MAGIC_VALUE = 0x07738135
|
const resetMagicValue = 0x07738135
|
||||||
|
|
||||||
// GPIO Pins
|
// GPIO Pins
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
package machine
|
package machine
|
||||||
|
|
||||||
// used to reset into bootloader
|
// used to reset into bootloader
|
||||||
const RESET_MAGIC_VALUE = 0x07738135
|
const resetMagicValue = 0x07738135
|
||||||
|
|
||||||
// GPIO Pins
|
// GPIO Pins
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
package machine
|
package machine
|
||||||
|
|
||||||
// used to reset into bootloader
|
// used to reset into bootloader
|
||||||
const RESET_MAGIC_VALUE = 0x07738135
|
const resetMagicValue = 0x07738135
|
||||||
|
|
||||||
// GPIO Pins
|
// GPIO Pins
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
package machine
|
package machine
|
||||||
|
|
||||||
// used to reset into bootloader
|
// used to reset into bootloader
|
||||||
const RESET_MAGIC_VALUE = 0x07738135
|
const resetMagicValue = 0x07738135
|
||||||
|
|
||||||
// GPIO Pins - Digital Low
|
// GPIO Pins - Digital Low
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Definition for compatibility, but not used
|
// Definition for compatibility, but not used
|
||||||
const RESET_MAGIC_VALUE = 0x00000000
|
const resetMagicValue = 0x00000000
|
||||||
|
|
||||||
const (
|
const (
|
||||||
LED = PC18
|
LED = PC18
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
package machine
|
package machine
|
||||||
|
|
||||||
// used to reset into bootloader
|
// used to reset into bootloader
|
||||||
const RESET_MAGIC_VALUE = 0xf01669ef
|
const resetMagicValue = 0xf01669ef
|
||||||
|
|
||||||
// GPIO Pins
|
// GPIO Pins
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
package machine
|
package machine
|
||||||
|
|
||||||
// used to reset into bootloader
|
// used to reset into bootloader
|
||||||
const RESET_MAGIC_VALUE = 0xf01669ef
|
const resetMagicValue = 0xf01669ef
|
||||||
|
|
||||||
// GPIO Pins
|
// GPIO Pins
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// used to reset into bootloader
|
// used to reset into bootloader
|
||||||
const RESET_MAGIC_VALUE = 0xf01669ef
|
const resetMagicValue = 0xf01669ef
|
||||||
|
|
||||||
// GPIO Pins
|
// GPIO Pins
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
package machine
|
package machine
|
||||||
|
|
||||||
// used to reset into bootloader
|
// used to reset into bootloader
|
||||||
const RESET_MAGIC_VALUE = 0xf01669ef
|
const resetMagicValue = 0xf01669ef
|
||||||
|
|
||||||
// GPIO Pins
|
// GPIO Pins
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -245,7 +245,7 @@ const (
|
|||||||
|
|
||||||
// Other peripheral constants
|
// Other peripheral constants
|
||||||
const (
|
const (
|
||||||
RESET_MAGIC_VALUE = 0xF01669EF // Used to reset into bootloader
|
resetMagicValue = 0xF01669EF // Used to reset into bootloader
|
||||||
)
|
)
|
||||||
|
|
||||||
// USB CDC pins
|
// USB CDC pins
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
package machine
|
package machine
|
||||||
|
|
||||||
// used to reset into bootloader
|
// used to reset into bootloader
|
||||||
const RESET_MAGIC_VALUE = 0xf01669ef
|
const resetMagicValue = 0xf01669ef
|
||||||
|
|
||||||
// GPIO Pins
|
// GPIO Pins
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
package machine
|
package machine
|
||||||
|
|
||||||
// used to reset into bootloader
|
// used to reset into bootloader
|
||||||
const RESET_MAGIC_VALUE = 0xf01669ef
|
const resetMagicValue = 0xf01669ef
|
||||||
|
|
||||||
// GPIO Pins
|
// GPIO Pins
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
package machine
|
package machine
|
||||||
|
|
||||||
// used to reset into bootloader
|
// used to reset into bootloader
|
||||||
const RESET_MAGIC_VALUE = 0xF01669EF
|
const resetMagicValue = 0xF01669EF
|
||||||
|
|
||||||
// Digital pins
|
// Digital pins
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
package machine
|
package machine
|
||||||
|
|
||||||
// used to reset into bootloader
|
// used to reset into bootloader
|
||||||
const RESET_MAGIC_VALUE = 0xf01669ef
|
const resetMagicValue = 0xf01669ef
|
||||||
|
|
||||||
// GPIO Pins
|
// GPIO Pins
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
package machine
|
package machine
|
||||||
|
|
||||||
// used to reset into bootloader
|
// used to reset into bootloader
|
||||||
const RESET_MAGIC_VALUE = 0x07738135
|
const resetMagicValue = 0x07738135
|
||||||
|
|
||||||
// Note: On the P1AM-100, pins D8, D9, D10, A3, and A4 are used for
|
// Note: On the P1AM-100, pins D8, D9, D10, A3, and A4 are used for
|
||||||
// communication with the base controller.
|
// communication with the base controller.
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
package machine
|
package machine
|
||||||
|
|
||||||
// used to reset into bootloader
|
// used to reset into bootloader
|
||||||
const RESET_MAGIC_VALUE = 0xf01669ef
|
const resetMagicValue = 0xf01669ef
|
||||||
|
|
||||||
// GPIO Pins
|
// GPIO Pins
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
package machine
|
package machine
|
||||||
|
|
||||||
// used to reset into bootloader
|
// used to reset into bootloader
|
||||||
const RESET_MAGIC_VALUE = 0xf01669ef
|
const resetMagicValue = 0xf01669ef
|
||||||
|
|
||||||
// GPIO Pins
|
// GPIO Pins
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
package machine
|
package machine
|
||||||
|
|
||||||
// used to reset into bootloader
|
// used to reset into bootloader
|
||||||
const RESET_MAGIC_VALUE = 0xf01669ef
|
const resetMagicValue = 0xf01669ef
|
||||||
|
|
||||||
// GPIO Pins
|
// GPIO Pins
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
package machine
|
package machine
|
||||||
|
|
||||||
// used to reset into bootloader
|
// used to reset into bootloader
|
||||||
const RESET_MAGIC_VALUE = 0xf01669ef
|
const resetMagicValue = 0xf01669ef
|
||||||
|
|
||||||
// GPIO Pins
|
// GPIO Pins
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
package machine
|
package machine
|
||||||
|
|
||||||
// used to reset into bootloader
|
// used to reset into bootloader
|
||||||
const RESET_MAGIC_VALUE = 0xf01669ef
|
const resetMagicValue = 0xf01669ef
|
||||||
|
|
||||||
// GPIO Pins
|
// GPIO Pins
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
package machine
|
package machine
|
||||||
|
|
||||||
// used to reset into bootloader
|
// used to reset into bootloader
|
||||||
const RESET_MAGIC_VALUE = 0xf01669ef
|
const resetMagicValue = 0xf01669ef
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ADC0 = A0
|
ADC0 = A0
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ const (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
usb_VID uint16 = 0x2886
|
usb_VID uint16 = 0x2886
|
||||||
usb_PID uint16 = 0x0045
|
usb_PID uint16 = 0x8045
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
package machine
|
package machine
|
||||||
|
|
||||||
// used to reset into bootloader
|
// used to reset into bootloader
|
||||||
const RESET_MAGIC_VALUE = 0xf01669ef
|
const resetMagicValue = 0xf01669ef
|
||||||
|
|
||||||
// GPIO Pins
|
// GPIO Pins
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// TWI_FREQ is the I2C bus speed. Normally either 100 kHz, or 400 kHz for high-speed bus.
|
// TWI_FREQ is the I2C bus speed. Normally either 100 kHz, or 400 kHz for high-speed bus.
|
||||||
|
//
|
||||||
|
// Deprecated: use 100 * machine.KHz or 400 * machine.KHz instead.
|
||||||
const (
|
const (
|
||||||
TWI_FREQ_100KHZ = 100000
|
TWI_FREQ_100KHZ = 100000
|
||||||
TWI_FREQ_400KHZ = 400000
|
TWI_FREQ_400KHZ = 400000
|
||||||
|
|||||||
@@ -18,6 +18,13 @@ var (
|
|||||||
// particular chip but instead runs in WebAssembly for example.
|
// particular chip but instead runs in WebAssembly for example.
|
||||||
const Device = deviceName
|
const Device = deviceName
|
||||||
|
|
||||||
|
// Generic constants.
|
||||||
|
const (
|
||||||
|
KHz = 1000
|
||||||
|
MHz = 1000_000
|
||||||
|
GHz = 1000_000_000
|
||||||
|
)
|
||||||
|
|
||||||
// PinMode sets the direction and pull mode of the pin. For example, PinOutput
|
// PinMode sets the direction and pull mode of the pin. For example, PinOutput
|
||||||
// sets the pin as an output and PinInputPullup sets the pin as an input with a
|
// sets the pin as an output and PinInputPullup sets the pin as an input with a
|
||||||
// pull-up.
|
// pull-up.
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ type I2CConfig struct {
|
|||||||
func (i2c *I2C) Configure(config I2CConfig) error {
|
func (i2c *I2C) Configure(config I2CConfig) error {
|
||||||
// Default I2C bus speed is 100 kHz.
|
// Default I2C bus speed is 100 kHz.
|
||||||
if config.Frequency == 0 {
|
if config.Frequency == 0 {
|
||||||
config.Frequency = TWI_FREQ_100KHZ
|
config.Frequency = 100 * KHz
|
||||||
}
|
}
|
||||||
|
|
||||||
// Activate internal pullups for twi.
|
// Activate internal pullups for twi.
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ package machine
|
|||||||
import (
|
import (
|
||||||
"device/arm"
|
"device/arm"
|
||||||
"device/sam"
|
"device/sam"
|
||||||
"errors"
|
|
||||||
"runtime/interrupt"
|
"runtime/interrupt"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
@@ -18,20 +17,20 @@ import (
|
|||||||
const deviceName = sam.Device
|
const deviceName = sam.Device
|
||||||
|
|
||||||
const (
|
const (
|
||||||
PinAnalog PinMode = 1
|
|
||||||
PinSERCOM PinMode = 2
|
|
||||||
PinSERCOMAlt PinMode = 3
|
|
||||||
PinTimer PinMode = 4
|
|
||||||
PinTimerAlt PinMode = 5
|
|
||||||
PinCom PinMode = 6
|
|
||||||
//PinAC_CLK PinMode = 7
|
|
||||||
PinDigital PinMode = 8
|
|
||||||
PinInput PinMode = 9
|
PinInput PinMode = 9
|
||||||
PinInputPullup PinMode = 10
|
PinInputPullup PinMode = 10
|
||||||
PinOutput PinMode = 11
|
PinOutput PinMode = 11
|
||||||
PinTCC PinMode = PinTimer
|
|
||||||
PinTCCAlt PinMode = PinTimerAlt
|
|
||||||
PinInputPulldown PinMode = 12
|
PinInputPulldown PinMode = 12
|
||||||
|
|
||||||
|
// internal pin modes
|
||||||
|
pinAnalog PinMode = 1
|
||||||
|
pinSERCOM PinMode = 2
|
||||||
|
pinSERCOMAlt PinMode = 3
|
||||||
|
pinTCC PinMode = 4
|
||||||
|
pinTCCAlt PinMode = 5
|
||||||
|
pinCom PinMode = 6
|
||||||
|
//PinAC_CLK PinMode = 7
|
||||||
|
pinDigital PinMode = 8
|
||||||
)
|
)
|
||||||
|
|
||||||
type PinChange uint8
|
type PinChange uint8
|
||||||
@@ -150,7 +149,7 @@ func findPinPadMapping(sercom uint8, pin Pin) (pinMode PinMode, pad uint32, ok b
|
|||||||
if upper != 0 {
|
if upper != 0 {
|
||||||
// SERCOM
|
// SERCOM
|
||||||
if (upper>>1)-1 == sercom {
|
if (upper>>1)-1 == sercom {
|
||||||
pinMode = PinSERCOM
|
pinMode = pinSERCOM
|
||||||
pad |= uint32((upper & 1) << 1)
|
pad |= uint32((upper & 1) << 1)
|
||||||
ok = true
|
ok = true
|
||||||
}
|
}
|
||||||
@@ -158,7 +157,7 @@ func findPinPadMapping(sercom uint8, pin Pin) (pinMode PinMode, pad uint32, ok b
|
|||||||
if lower != 0 {
|
if lower != 0 {
|
||||||
// SERCOM-ALT
|
// SERCOM-ALT
|
||||||
if (lower>>1)-1 == sercom {
|
if (lower>>1)-1 == sercom {
|
||||||
pinMode = PinSERCOMAlt
|
pinMode = pinSERCOMAlt
|
||||||
pad |= uint32((lower & 1) << 1)
|
pad |= uint32((lower & 1) << 1)
|
||||||
ok = true
|
ok = true
|
||||||
}
|
}
|
||||||
@@ -382,7 +381,7 @@ func (a ADC) Configure(config ADCConfig) {
|
|||||||
// 1/2 VDDANA = 0.5 * 3V3 = 1.65V
|
// 1/2 VDDANA = 0.5 * 3V3 = 1.65V
|
||||||
sam.ADC.REFCTRL.SetBits(sam.ADC_REFCTRL_REFSEL_INTVCC1 << sam.ADC_REFCTRL_REFSEL_Pos)
|
sam.ADC.REFCTRL.SetBits(sam.ADC_REFCTRL_REFSEL_INTVCC1 << sam.ADC_REFCTRL_REFSEL_Pos)
|
||||||
|
|
||||||
a.Pin.Configure(PinConfig{Mode: PinAnalog})
|
a.Pin.Configure(PinConfig{Mode: pinAnalog})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -677,7 +676,7 @@ const i2cTimeout = 1000
|
|||||||
func (i2c *I2C) Configure(config I2CConfig) error {
|
func (i2c *I2C) Configure(config I2CConfig) error {
|
||||||
// Default I2C bus speed is 100 kHz.
|
// Default I2C bus speed is 100 kHz.
|
||||||
if config.Frequency == 0 {
|
if config.Frequency == 0 {
|
||||||
config.Frequency = TWI_FREQ_100KHZ
|
config.Frequency = 100 * KHz
|
||||||
}
|
}
|
||||||
if config.SDA == 0 && config.SCL == 0 {
|
if config.SDA == 0 && config.SCL == 0 {
|
||||||
config.SDA = SDA_PIN
|
config.SDA = SDA_PIN
|
||||||
@@ -1001,11 +1000,11 @@ func (i2s I2S) Configure(config I2SConfig) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// configure pin for clock
|
// configure pin for clock
|
||||||
config.SCK.Configure(PinConfig{Mode: PinCom})
|
config.SCK.Configure(PinConfig{Mode: pinCom})
|
||||||
|
|
||||||
// configure pin for WS, if needed
|
// configure pin for WS, if needed
|
||||||
if config.WS != NoPin {
|
if config.WS != NoPin {
|
||||||
config.WS.Configure(PinConfig{Mode: PinCom})
|
config.WS.Configure(PinConfig{Mode: pinCom})
|
||||||
}
|
}
|
||||||
|
|
||||||
// now set serializer data size.
|
// now set serializer data size.
|
||||||
@@ -1044,7 +1043,7 @@ func (i2s I2S) Configure(config I2SConfig) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// configure data pin
|
// configure data pin
|
||||||
config.SD.Configure(PinConfig{Mode: PinCom})
|
config.SD.Configure(PinConfig{Mode: pinCom})
|
||||||
|
|
||||||
// re-enable
|
// re-enable
|
||||||
i2s.Bus.CTRLA.SetBits(sam.I2S_CTRLA_ENABLE)
|
i2s.Bus.CTRLA.SetBits(sam.I2S_CTRLA_ENABLE)
|
||||||
@@ -1274,10 +1273,6 @@ 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
|
// 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.
|
// 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.
|
// The Tx method knows about this, and offers a few different ways of calling it.
|
||||||
@@ -1641,12 +1636,12 @@ func findPinTimerMapping(timer uint8, pin Pin) (PinMode, uint8) {
|
|||||||
if mapping&0x07 == timer+1 {
|
if mapping&0x07 == timer+1 {
|
||||||
// PWM output is on peripheral function E.
|
// PWM output is on peripheral function E.
|
||||||
evenChannel := ((mapping >> 3) & 1) * 2
|
evenChannel := ((mapping >> 3) & 1) * 2
|
||||||
return PinTCC, evenChannel + uint8(pin&1)
|
return pinTCC, evenChannel + uint8(pin&1)
|
||||||
}
|
}
|
||||||
if (mapping&0x70)>>4 == timer+1 {
|
if (mapping&0x70)>>4 == timer+1 {
|
||||||
// PWM output is on peripheral function F.
|
// PWM output is on peripheral function F.
|
||||||
evenChannel := ((mapping >> 7) & 1) * 2
|
evenChannel := ((mapping >> 7) & 1) * 2
|
||||||
return PinTCCAlt, evenChannel + uint8(pin&1)
|
return pinTCCAlt, evenChannel + uint8(pin&1)
|
||||||
}
|
}
|
||||||
return 0, 0
|
return 0, 0
|
||||||
}
|
}
|
||||||
@@ -1740,7 +1735,7 @@ func EnterBootloader() {
|
|||||||
|
|
||||||
// Perform magic reset into bootloader, as mentioned in
|
// Perform magic reset into bootloader, as mentioned in
|
||||||
// https://github.com/arduino/ArduinoCore-samd/issues/197
|
// https://github.com/arduino/ArduinoCore-samd/issues/197
|
||||||
*(*uint32)(unsafe.Pointer(uintptr(0x20007FFC))) = RESET_MAGIC_VALUE
|
*(*uint32)(unsafe.Pointer(uintptr(0x20007FFC))) = resetMagicValue
|
||||||
|
|
||||||
arm.SystemReset()
|
arm.SystemReset()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,8 @@ func (dev *USBDevice) Configure(config UARTConfig) {
|
|||||||
sam.USB_DEVICE.DESCADD.Set(uint32(uintptr(unsafe.Pointer(&usbEndpointDescriptors))))
|
sam.USB_DEVICE.DESCADD.Set(uint32(uintptr(unsafe.Pointer(&usbEndpointDescriptors))))
|
||||||
|
|
||||||
// configure pins
|
// configure pins
|
||||||
USBCDC_DM_PIN.Configure(PinConfig{Mode: PinCom})
|
USBCDC_DM_PIN.Configure(PinConfig{Mode: pinCom})
|
||||||
USBCDC_DP_PIN.Configure(PinConfig{Mode: PinCom})
|
USBCDC_DP_PIN.Configure(PinConfig{Mode: pinCom})
|
||||||
|
|
||||||
// performs pad calibration from store fuses
|
// performs pad calibration from store fuses
|
||||||
handlePadCalibration()
|
handlePadCalibration()
|
||||||
|
|||||||
@@ -86,53 +86,53 @@ func (p Pin) Configure(config PinConfig) {
|
|||||||
sam.PORT.OUTSET0.Set(1 << uint8(p))
|
sam.PORT.OUTSET0.Set(1 << uint8(p))
|
||||||
p.setPinCfg(sam.PORT_PINCFG0_INEN | sam.PORT_PINCFG0_PULLEN)
|
p.setPinCfg(sam.PORT_PINCFG0_INEN | sam.PORT_PINCFG0_PULLEN)
|
||||||
|
|
||||||
case PinSERCOM:
|
case pinSERCOM:
|
||||||
if uint8(p)&1 > 0 {
|
if uint8(p)&1 > 0 {
|
||||||
// odd pin, so save the even pins
|
// odd pin, so save the even pins
|
||||||
val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk
|
val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk
|
||||||
p.setPMux(val | (uint8(PinSERCOM) << sam.PORT_PMUX0_PMUXO_Pos))
|
p.setPMux(val | (uint8(pinSERCOM) << sam.PORT_PMUX0_PMUXO_Pos))
|
||||||
} else {
|
} else {
|
||||||
// even pin, so save the odd pins
|
// even pin, so save the odd pins
|
||||||
val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk
|
val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk
|
||||||
p.setPMux(val | (uint8(PinSERCOM) << sam.PORT_PMUX0_PMUXE_Pos))
|
p.setPMux(val | (uint8(pinSERCOM) << sam.PORT_PMUX0_PMUXE_Pos))
|
||||||
}
|
}
|
||||||
// enable port config
|
// enable port config
|
||||||
p.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR | sam.PORT_PINCFG0_INEN)
|
p.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR | sam.PORT_PINCFG0_INEN)
|
||||||
|
|
||||||
case PinSERCOMAlt:
|
case pinSERCOMAlt:
|
||||||
if uint8(p)&1 > 0 {
|
if uint8(p)&1 > 0 {
|
||||||
// odd pin, so save the even pins
|
// odd pin, so save the even pins
|
||||||
val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk
|
val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk
|
||||||
p.setPMux(val | (uint8(PinSERCOMAlt) << sam.PORT_PMUX0_PMUXO_Pos))
|
p.setPMux(val | (uint8(pinSERCOMAlt) << sam.PORT_PMUX0_PMUXO_Pos))
|
||||||
} else {
|
} else {
|
||||||
// even pin, so save the odd pins
|
// even pin, so save the odd pins
|
||||||
val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk
|
val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk
|
||||||
p.setPMux(val | (uint8(PinSERCOMAlt) << sam.PORT_PMUX0_PMUXE_Pos))
|
p.setPMux(val | (uint8(pinSERCOMAlt) << sam.PORT_PMUX0_PMUXE_Pos))
|
||||||
}
|
}
|
||||||
// enable port config
|
// enable port config
|
||||||
p.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR)
|
p.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR)
|
||||||
|
|
||||||
case PinCom:
|
case pinCom:
|
||||||
if uint8(p)&1 > 0 {
|
if uint8(p)&1 > 0 {
|
||||||
// odd pin, so save the even pins
|
// odd pin, so save the even pins
|
||||||
val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk
|
val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk
|
||||||
p.setPMux(val | (uint8(PinCom) << sam.PORT_PMUX0_PMUXO_Pos))
|
p.setPMux(val | (uint8(pinCom) << sam.PORT_PMUX0_PMUXO_Pos))
|
||||||
} else {
|
} else {
|
||||||
// even pin, so save the odd pins
|
// even pin, so save the odd pins
|
||||||
val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk
|
val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk
|
||||||
p.setPMux(val | (uint8(PinCom) << sam.PORT_PMUX0_PMUXE_Pos))
|
p.setPMux(val | (uint8(pinCom) << sam.PORT_PMUX0_PMUXE_Pos))
|
||||||
}
|
}
|
||||||
// enable port config
|
// enable port config
|
||||||
p.setPinCfg(sam.PORT_PINCFG0_PMUXEN)
|
p.setPinCfg(sam.PORT_PINCFG0_PMUXEN)
|
||||||
case PinAnalog:
|
case pinAnalog:
|
||||||
if uint8(p)&1 > 0 {
|
if uint8(p)&1 > 0 {
|
||||||
// odd pin, so save the even pins
|
// odd pin, so save the even pins
|
||||||
val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk
|
val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk
|
||||||
p.setPMux(val | (uint8(PinAnalog) << sam.PORT_PMUX0_PMUXO_Pos))
|
p.setPMux(val | (uint8(pinAnalog) << sam.PORT_PMUX0_PMUXO_Pos))
|
||||||
} else {
|
} else {
|
||||||
// even pin, so save the odd pins
|
// even pin, so save the odd pins
|
||||||
val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk
|
val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk
|
||||||
p.setPMux(val | (uint8(PinAnalog) << sam.PORT_PMUX0_PMUXE_Pos))
|
p.setPMux(val | (uint8(pinAnalog) << sam.PORT_PMUX0_PMUXE_Pos))
|
||||||
}
|
}
|
||||||
// enable port config
|
// enable port config
|
||||||
p.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR)
|
p.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR)
|
||||||
|
|||||||
@@ -137,53 +137,53 @@ func (p Pin) Configure(config PinConfig) {
|
|||||||
p.setPinCfg(sam.PORT_PINCFG0_INEN | sam.PORT_PINCFG0_PULLEN)
|
p.setPinCfg(sam.PORT_PINCFG0_INEN | sam.PORT_PINCFG0_PULLEN)
|
||||||
}
|
}
|
||||||
|
|
||||||
case PinSERCOM:
|
case pinSERCOM:
|
||||||
if p&1 > 0 {
|
if p&1 > 0 {
|
||||||
// odd pin, so save the even pins
|
// odd pin, so save the even pins
|
||||||
val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk
|
val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk
|
||||||
p.setPMux(val | (uint8(PinSERCOM) << sam.PORT_PMUX0_PMUXO_Pos))
|
p.setPMux(val | (uint8(pinSERCOM) << sam.PORT_PMUX0_PMUXO_Pos))
|
||||||
} else {
|
} else {
|
||||||
// even pin, so save the odd pins
|
// even pin, so save the odd pins
|
||||||
val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk
|
val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk
|
||||||
p.setPMux(val | (uint8(PinSERCOM) << sam.PORT_PMUX0_PMUXE_Pos))
|
p.setPMux(val | (uint8(pinSERCOM) << sam.PORT_PMUX0_PMUXE_Pos))
|
||||||
}
|
}
|
||||||
// enable port config
|
// enable port config
|
||||||
p.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR | sam.PORT_PINCFG0_INEN)
|
p.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR | sam.PORT_PINCFG0_INEN)
|
||||||
|
|
||||||
case PinSERCOMAlt:
|
case pinSERCOMAlt:
|
||||||
if p&1 > 0 {
|
if p&1 > 0 {
|
||||||
// odd pin, so save the even pins
|
// odd pin, so save the even pins
|
||||||
val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk
|
val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk
|
||||||
p.setPMux(val | (uint8(PinSERCOMAlt) << sam.PORT_PMUX0_PMUXO_Pos))
|
p.setPMux(val | (uint8(pinSERCOMAlt) << sam.PORT_PMUX0_PMUXO_Pos))
|
||||||
} else {
|
} else {
|
||||||
// even pin, so save the odd pins
|
// even pin, so save the odd pins
|
||||||
val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk
|
val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk
|
||||||
p.setPMux(val | (uint8(PinSERCOMAlt) << sam.PORT_PMUX0_PMUXE_Pos))
|
p.setPMux(val | (uint8(pinSERCOMAlt) << sam.PORT_PMUX0_PMUXE_Pos))
|
||||||
}
|
}
|
||||||
// enable port config
|
// enable port config
|
||||||
p.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR)
|
p.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR)
|
||||||
|
|
||||||
case PinCom:
|
case pinCom:
|
||||||
if p&1 > 0 {
|
if p&1 > 0 {
|
||||||
// odd pin, so save the even pins
|
// odd pin, so save the even pins
|
||||||
val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk
|
val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk
|
||||||
p.setPMux(val | (uint8(PinCom) << sam.PORT_PMUX0_PMUXO_Pos))
|
p.setPMux(val | (uint8(pinCom) << sam.PORT_PMUX0_PMUXO_Pos))
|
||||||
} else {
|
} else {
|
||||||
// even pin, so save the odd pins
|
// even pin, so save the odd pins
|
||||||
val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk
|
val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk
|
||||||
p.setPMux(val | (uint8(PinCom) << sam.PORT_PMUX0_PMUXE_Pos))
|
p.setPMux(val | (uint8(pinCom) << sam.PORT_PMUX0_PMUXE_Pos))
|
||||||
}
|
}
|
||||||
// enable port config
|
// enable port config
|
||||||
p.setPinCfg(sam.PORT_PINCFG0_PMUXEN)
|
p.setPinCfg(sam.PORT_PINCFG0_PMUXEN)
|
||||||
case PinAnalog:
|
case pinAnalog:
|
||||||
if p&1 > 0 {
|
if p&1 > 0 {
|
||||||
// odd pin, so save the even pins
|
// odd pin, so save the even pins
|
||||||
val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk
|
val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk
|
||||||
p.setPMux(val | (uint8(PinAnalog) << sam.PORT_PMUX0_PMUXO_Pos))
|
p.setPMux(val | (uint8(pinAnalog) << sam.PORT_PMUX0_PMUXO_Pos))
|
||||||
} else {
|
} else {
|
||||||
// even pin, so save the odd pins
|
// even pin, so save the odd pins
|
||||||
val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk
|
val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk
|
||||||
p.setPMux(val | (uint8(PinAnalog) << sam.PORT_PMUX0_PMUXE_Pos))
|
p.setPMux(val | (uint8(pinAnalog) << sam.PORT_PMUX0_PMUXE_Pos))
|
||||||
}
|
}
|
||||||
// enable port config
|
// enable port config
|
||||||
p.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR)
|
p.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR)
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ package machine
|
|||||||
import (
|
import (
|
||||||
"device/arm"
|
"device/arm"
|
||||||
"device/sam"
|
"device/sam"
|
||||||
"errors"
|
|
||||||
"runtime/interrupt"
|
"runtime/interrupt"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
@@ -22,30 +21,29 @@ func CPUFrequency() uint32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
PinAnalog PinMode = 1
|
|
||||||
PinSERCOM PinMode = 2
|
|
||||||
PinSERCOMAlt PinMode = 3
|
|
||||||
PinTimer PinMode = 4
|
|
||||||
PinTimerAlt PinMode = 5
|
|
||||||
PinTCCPDEC PinMode = 6
|
|
||||||
PinCom PinMode = 7
|
|
||||||
PinSDHC PinMode = 8
|
|
||||||
PinI2S PinMode = 9
|
|
||||||
PinPCC PinMode = 10
|
|
||||||
PinGMAC PinMode = 11
|
|
||||||
PinACCLK PinMode = 12
|
|
||||||
PinCCL PinMode = 13
|
|
||||||
PinDigital PinMode = 14
|
|
||||||
PinInput PinMode = 15
|
PinInput PinMode = 15
|
||||||
PinInputPullup PinMode = 16
|
PinInputPullup PinMode = 16
|
||||||
PinOutput PinMode = 17
|
PinOutput PinMode = 17
|
||||||
PinTCCE PinMode = PinTimer
|
|
||||||
PinTCCF PinMode = PinTimerAlt
|
|
||||||
PinTCCG PinMode = PinTCCPDEC
|
|
||||||
PinInputPulldown PinMode = 18
|
PinInputPulldown PinMode = 18
|
||||||
PinCAN PinMode = 19
|
|
||||||
PinCAN0 PinMode = PinSDHC
|
// internal pin modes
|
||||||
PinCAN1 PinMode = PinCom
|
pinAnalog PinMode = 1
|
||||||
|
pinSERCOM PinMode = 2
|
||||||
|
pinSERCOMAlt PinMode = 3
|
||||||
|
pinTCCE PinMode = 4
|
||||||
|
pinTCCF PinMode = 5
|
||||||
|
pinTCCG PinMode = 6
|
||||||
|
pinCom PinMode = 7
|
||||||
|
pinSDHC PinMode = 8
|
||||||
|
pinI2S PinMode = 9
|
||||||
|
pinPCC PinMode = 10
|
||||||
|
pinGMAC PinMode = 11
|
||||||
|
pinACCLK PinMode = 12
|
||||||
|
pinCCL PinMode = 13
|
||||||
|
pinDigital PinMode = 14
|
||||||
|
pinCAN PinMode = 19
|
||||||
|
pinCAN0 PinMode = pinSDHC
|
||||||
|
pinCAN1 PinMode = pinCom
|
||||||
)
|
)
|
||||||
|
|
||||||
type PinChange uint8
|
type PinChange uint8
|
||||||
@@ -339,7 +337,7 @@ func findPinPadMapping(sercom uint8, pin Pin) (pinMode PinMode, pad uint32, ok b
|
|||||||
if upper != 0 {
|
if upper != 0 {
|
||||||
// SERCOM
|
// SERCOM
|
||||||
if (upper>>4)-1 == sercom {
|
if (upper>>4)-1 == sercom {
|
||||||
pinMode = PinSERCOM
|
pinMode = pinSERCOM
|
||||||
pad |= uint32(upper % 4)
|
pad |= uint32(upper % 4)
|
||||||
ok = true
|
ok = true
|
||||||
}
|
}
|
||||||
@@ -347,7 +345,7 @@ func findPinPadMapping(sercom uint8, pin Pin) (pinMode PinMode, pad uint32, ok b
|
|||||||
if lower != 0 {
|
if lower != 0 {
|
||||||
// SERCOM-ALT
|
// SERCOM-ALT
|
||||||
if (lower>>4)-1 == sercom {
|
if (lower>>4)-1 == sercom {
|
||||||
pinMode = PinSERCOMAlt
|
pinMode = pinSERCOMAlt
|
||||||
pad |= uint32(lower % 4)
|
pad |= uint32(lower % 4)
|
||||||
ok = true
|
ok = true
|
||||||
}
|
}
|
||||||
@@ -581,65 +579,65 @@ func (p Pin) Configure(config PinConfig) {
|
|||||||
sam.PORT.GROUP[group].OUTSET.Set(1 << pin_in_group)
|
sam.PORT.GROUP[group].OUTSET.Set(1 << pin_in_group)
|
||||||
p.setPinCfg(sam.PORT_GROUP_PINCFG_INEN | sam.PORT_GROUP_PINCFG_PULLEN)
|
p.setPinCfg(sam.PORT_GROUP_PINCFG_INEN | sam.PORT_GROUP_PINCFG_PULLEN)
|
||||||
|
|
||||||
case PinSERCOM:
|
case pinSERCOM:
|
||||||
if p&1 > 0 {
|
if p&1 > 0 {
|
||||||
// odd pin, so save the even pins
|
// odd pin, so save the even pins
|
||||||
val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXE_Msk
|
val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXE_Msk
|
||||||
p.setPMux(val | (uint8(PinSERCOM) << sam.PORT_GROUP_PMUX_PMUXO_Pos))
|
p.setPMux(val | (uint8(pinSERCOM) << sam.PORT_GROUP_PMUX_PMUXO_Pos))
|
||||||
} else {
|
} else {
|
||||||
// even pin, so save the odd pins
|
// even pin, so save the odd pins
|
||||||
val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXO_Msk
|
val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXO_Msk
|
||||||
p.setPMux(val | (uint8(PinSERCOM) << sam.PORT_GROUP_PMUX_PMUXE_Pos))
|
p.setPMux(val | (uint8(pinSERCOM) << sam.PORT_GROUP_PMUX_PMUXE_Pos))
|
||||||
}
|
}
|
||||||
// enable port config
|
// enable port config
|
||||||
p.setPinCfg(sam.PORT_GROUP_PINCFG_PMUXEN | sam.PORT_GROUP_PINCFG_DRVSTR | sam.PORT_GROUP_PINCFG_INEN)
|
p.setPinCfg(sam.PORT_GROUP_PINCFG_PMUXEN | sam.PORT_GROUP_PINCFG_DRVSTR | sam.PORT_GROUP_PINCFG_INEN)
|
||||||
|
|
||||||
case PinSERCOMAlt:
|
case pinSERCOMAlt:
|
||||||
if p&1 > 0 {
|
if p&1 > 0 {
|
||||||
// odd pin, so save the even pins
|
// odd pin, so save the even pins
|
||||||
val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXE_Msk
|
val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXE_Msk
|
||||||
p.setPMux(val | (uint8(PinSERCOMAlt) << sam.PORT_GROUP_PMUX_PMUXO_Pos))
|
p.setPMux(val | (uint8(pinSERCOMAlt) << sam.PORT_GROUP_PMUX_PMUXO_Pos))
|
||||||
} else {
|
} else {
|
||||||
// even pin, so save the odd pins
|
// even pin, so save the odd pins
|
||||||
val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXO_Msk
|
val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXO_Msk
|
||||||
p.setPMux(val | (uint8(PinSERCOMAlt) << sam.PORT_GROUP_PMUX_PMUXE_Pos))
|
p.setPMux(val | (uint8(pinSERCOMAlt) << sam.PORT_GROUP_PMUX_PMUXE_Pos))
|
||||||
}
|
}
|
||||||
// enable port config
|
// enable port config
|
||||||
p.setPinCfg(sam.PORT_GROUP_PINCFG_PMUXEN | sam.PORT_GROUP_PINCFG_DRVSTR)
|
p.setPinCfg(sam.PORT_GROUP_PINCFG_PMUXEN | sam.PORT_GROUP_PINCFG_DRVSTR)
|
||||||
|
|
||||||
case PinCom:
|
case pinCom:
|
||||||
if p&1 > 0 {
|
if p&1 > 0 {
|
||||||
// odd pin, so save the even pins
|
// odd pin, so save the even pins
|
||||||
val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXE_Msk
|
val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXE_Msk
|
||||||
p.setPMux(val | (uint8(PinCom) << sam.PORT_GROUP_PMUX_PMUXO_Pos))
|
p.setPMux(val | (uint8(pinCom) << sam.PORT_GROUP_PMUX_PMUXO_Pos))
|
||||||
} else {
|
} else {
|
||||||
// even pin, so save the odd pins
|
// even pin, so save the odd pins
|
||||||
val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXO_Msk
|
val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXO_Msk
|
||||||
p.setPMux(val | (uint8(PinCom) << sam.PORT_GROUP_PMUX_PMUXE_Pos))
|
p.setPMux(val | (uint8(pinCom) << sam.PORT_GROUP_PMUX_PMUXE_Pos))
|
||||||
}
|
}
|
||||||
// enable port config
|
// enable port config
|
||||||
p.setPinCfg(sam.PORT_GROUP_PINCFG_PMUXEN)
|
p.setPinCfg(sam.PORT_GROUP_PINCFG_PMUXEN)
|
||||||
case PinAnalog:
|
case pinAnalog:
|
||||||
if p&1 > 0 {
|
if p&1 > 0 {
|
||||||
// odd pin, so save the even pins
|
// odd pin, so save the even pins
|
||||||
val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXE_Msk
|
val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXE_Msk
|
||||||
p.setPMux(val | (uint8(PinAnalog) << sam.PORT_GROUP_PMUX_PMUXO_Pos))
|
p.setPMux(val | (uint8(pinAnalog) << sam.PORT_GROUP_PMUX_PMUXO_Pos))
|
||||||
} else {
|
} else {
|
||||||
// even pin, so save the odd pins
|
// even pin, so save the odd pins
|
||||||
val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXO_Msk
|
val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXO_Msk
|
||||||
p.setPMux(val | (uint8(PinAnalog) << sam.PORT_GROUP_PMUX_PMUXE_Pos))
|
p.setPMux(val | (uint8(pinAnalog) << sam.PORT_GROUP_PMUX_PMUXE_Pos))
|
||||||
}
|
}
|
||||||
// enable port config
|
// enable port config
|
||||||
p.setPinCfg(sam.PORT_GROUP_PINCFG_PMUXEN | sam.PORT_GROUP_PINCFG_DRVSTR)
|
p.setPinCfg(sam.PORT_GROUP_PINCFG_PMUXEN | sam.PORT_GROUP_PINCFG_DRVSTR)
|
||||||
case PinSDHC:
|
case pinSDHC:
|
||||||
if p&1 > 0 {
|
if p&1 > 0 {
|
||||||
// odd pin, so save the even pins
|
// odd pin, so save the even pins
|
||||||
val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXE_Msk
|
val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXE_Msk
|
||||||
p.setPMux(val | (uint8(PinSDHC) << sam.PORT_GROUP_PMUX_PMUXO_Pos))
|
p.setPMux(val | (uint8(pinSDHC) << sam.PORT_GROUP_PMUX_PMUXO_Pos))
|
||||||
} else {
|
} else {
|
||||||
// even pin, so save the odd pins
|
// even pin, so save the odd pins
|
||||||
val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXO_Msk
|
val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXO_Msk
|
||||||
p.setPMux(val | (uint8(PinSDHC) << sam.PORT_GROUP_PMUX_PMUXE_Pos))
|
p.setPMux(val | (uint8(pinSDHC) << sam.PORT_GROUP_PMUX_PMUXE_Pos))
|
||||||
}
|
}
|
||||||
// enable port config
|
// enable port config
|
||||||
p.setPinCfg(sam.PORT_GROUP_PINCFG_PMUXEN)
|
p.setPinCfg(sam.PORT_GROUP_PINCFG_PMUXEN)
|
||||||
@@ -815,7 +813,7 @@ func (a ADC) Configure(config ADCConfig) {
|
|||||||
adc.REFCTRL.SetBits(sam.ADC_REFCTRL_REFSEL_INTVCC1)
|
adc.REFCTRL.SetBits(sam.ADC_REFCTRL_REFSEL_INTVCC1)
|
||||||
}
|
}
|
||||||
|
|
||||||
a.Pin.Configure(PinConfig{Mode: PinAnalog})
|
a.Pin.Configure(PinConfig{Mode: pinAnalog})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get returns the current value of a ADC pin, in the range 0..0xffff.
|
// Get returns the current value of a ADC pin, in the range 0..0xffff.
|
||||||
@@ -1151,7 +1149,7 @@ const i2cTimeout = 1000
|
|||||||
func (i2c *I2C) Configure(config I2CConfig) error {
|
func (i2c *I2C) Configure(config I2CConfig) error {
|
||||||
// Default I2C bus speed is 100 kHz.
|
// Default I2C bus speed is 100 kHz.
|
||||||
if config.Frequency == 0 {
|
if config.Frequency == 0 {
|
||||||
config.Frequency = TWI_FREQ_100KHZ
|
config.Frequency = 100 * KHz
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use default I2C pins if not set.
|
// Use default I2C pins if not set.
|
||||||
@@ -1527,10 +1525,6 @@ 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
|
// 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.
|
// 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.
|
// The Tx method knows about this, and offers a few different ways of calling it.
|
||||||
@@ -1872,7 +1866,7 @@ var pinTimerMapping = [...]struct{ F, G uint8 }{
|
|||||||
PB02 / 2: {pinTCC2_2, 0},
|
PB02 / 2: {pinTCC2_2, 0},
|
||||||
}
|
}
|
||||||
|
|
||||||
// findPinPadMapping returns the pin mode (PinTCCF or PinTCCG) and the channel
|
// findPinPadMapping returns the pin mode (pinTCCF or pinTCCG) and the channel
|
||||||
// number for a given timer and pin. A zero PinMode is returned if no mapping
|
// number for a given timer and pin. A zero PinMode is returned if no mapping
|
||||||
// could be found.
|
// could be found.
|
||||||
func findPinTimerMapping(timer uint8, pin Pin) (PinMode, uint8) {
|
func findPinTimerMapping(timer uint8, pin Pin) (PinMode, uint8) {
|
||||||
@@ -1884,12 +1878,12 @@ func findPinTimerMapping(timer uint8, pin Pin) (PinMode, uint8) {
|
|||||||
|
|
||||||
// Check for column F in the datasheet.
|
// Check for column F in the datasheet.
|
||||||
if mapping.F>>4-1 == timer {
|
if mapping.F>>4-1 == timer {
|
||||||
return PinTCCF, mapping.F&0x0f + uint8(pin)&1
|
return pinTCCF, mapping.F&0x0f + uint8(pin)&1
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for column G in the datasheet.
|
// Check for column G in the datasheet.
|
||||||
if mapping.G>>4-1 == timer {
|
if mapping.G>>4-1 == timer {
|
||||||
return PinTCCG, mapping.G&0x0f + uint8(pin)&1
|
return pinTCCG, mapping.G&0x0f + uint8(pin)&1
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nothing found.
|
// Nothing found.
|
||||||
@@ -1980,7 +1974,7 @@ func EnterBootloader() {
|
|||||||
|
|
||||||
// Perform magic reset into bootloader, as mentioned in
|
// Perform magic reset into bootloader, as mentioned in
|
||||||
// https://github.com/arduino/ArduinoCore-samd/issues/197
|
// https://github.com/arduino/ArduinoCore-samd/issues/197
|
||||||
*(*uint32)(unsafe.Pointer(uintptr(0x20000000 + HSRAM_SIZE - 4))) = RESET_MAGIC_VALUE
|
*(*uint32)(unsafe.Pointer(uintptr(0x20000000 + HSRAM_SIZE - 4))) = resetMagicValue
|
||||||
|
|
||||||
arm.SystemReset()
|
arm.SystemReset()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,8 @@ func (dev *USBDevice) Configure(config UARTConfig) {
|
|||||||
sam.USB_DEVICE.DESCADD.Set(uint32(uintptr(unsafe.Pointer(&usbEndpointDescriptors))))
|
sam.USB_DEVICE.DESCADD.Set(uint32(uintptr(unsafe.Pointer(&usbEndpointDescriptors))))
|
||||||
|
|
||||||
// configure pins
|
// configure pins
|
||||||
USBCDC_DM_PIN.Configure(PinConfig{Mode: PinCom})
|
USBCDC_DM_PIN.Configure(PinConfig{Mode: pinCom})
|
||||||
USBCDC_DP_PIN.Configure(PinConfig{Mode: PinCom})
|
USBCDC_DP_PIN.Configure(PinConfig{Mode: pinCom})
|
||||||
|
|
||||||
// performs pad calibration from store fuses
|
// performs pad calibration from store fuses
|
||||||
handlePadCalibration()
|
handlePadCalibration()
|
||||||
|
|||||||
@@ -68,9 +68,9 @@ func (can *CAN) Configure(config CANConfig) error {
|
|||||||
config.Standby.Low()
|
config.Standby.Low()
|
||||||
}
|
}
|
||||||
|
|
||||||
mode := PinCAN0
|
mode := pinCAN0
|
||||||
if can.instance() == 1 {
|
if can.instance() == 1 {
|
||||||
mode = PinCAN1
|
mode = pinCAN1
|
||||||
}
|
}
|
||||||
|
|
||||||
config.Rx.Configure(PinConfig{Mode: mode})
|
config.Rx.Configure(PinConfig{Mode: mode})
|
||||||
|
|||||||
@@ -59,12 +59,9 @@ type PinChange uint8
|
|||||||
|
|
||||||
// Pin change interrupt constants for SetInterrupt.
|
// Pin change interrupt constants for SetInterrupt.
|
||||||
const (
|
const (
|
||||||
PinNoInterrupt PinChange = iota
|
PinRising PinChange = iota + 1
|
||||||
PinRising
|
|
||||||
PinFalling
|
PinFalling
|
||||||
PinToggle
|
PinToggle
|
||||||
PinLowLevel
|
|
||||||
PinHighLevel
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Configure this pin with the given configuration.
|
// Configure this pin with the given configuration.
|
||||||
@@ -190,7 +187,7 @@ func (p Pin) SetInterrupt(change PinChange, callback func(Pin)) (err error) {
|
|||||||
return ErrInvalidInputPin
|
return ErrInvalidInputPin
|
||||||
}
|
}
|
||||||
|
|
||||||
if callback == nil || change == PinNoInterrupt {
|
if callback == nil {
|
||||||
// Disable this pin interrupt
|
// Disable this pin interrupt
|
||||||
p.pin().ClearBits(esp.GPIO_PIN_PIN_INT_TYPE_Msk | esp.GPIO_PIN_PIN_INT_ENA_Msk)
|
p.pin().ClearBits(esp.GPIO_PIN_PIN_INT_TYPE_Msk | esp.GPIO_PIN_PIN_INT_ENA_Msk)
|
||||||
|
|
||||||
@@ -264,15 +261,6 @@ type UART struct {
|
|||||||
DataOverflowDetected bool // set when data overflow detected in UART FIFO buffer or RingBuffer
|
DataOverflowDetected bool // set when data overflow detected in UART FIFO buffer or RingBuffer
|
||||||
}
|
}
|
||||||
|
|
||||||
type UARTStopBits int
|
|
||||||
|
|
||||||
const (
|
|
||||||
UARTStopBits_Default UARTStopBits = iota
|
|
||||||
UARTStopBits_1
|
|
||||||
UARTStopBits_1_5
|
|
||||||
UARTStopBits_2
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
defaultDataBits = 8
|
defaultDataBits = 8
|
||||||
defaultStopBit = 1
|
defaultStopBit = 1
|
||||||
|
|||||||
@@ -18,9 +18,11 @@ func CPUFrequency() uint32 {
|
|||||||
const (
|
const (
|
||||||
PinInput PinMode = iota
|
PinInput PinMode = iota
|
||||||
PinOutput
|
PinOutput
|
||||||
PinPWM
|
|
||||||
PinSPI
|
// internal pin modes
|
||||||
PinI2C = PinSPI
|
pinPWM
|
||||||
|
pinSPI
|
||||||
|
pinI2C = pinSPI
|
||||||
)
|
)
|
||||||
|
|
||||||
// Configure this pin with the given configuration.
|
// Configure this pin with the given configuration.
|
||||||
@@ -29,10 +31,10 @@ func (p Pin) Configure(config PinConfig) {
|
|||||||
switch config.Mode {
|
switch config.Mode {
|
||||||
case PinOutput:
|
case PinOutput:
|
||||||
sifive.GPIO0.OUTPUT_EN.SetBits(1 << uint8(p))
|
sifive.GPIO0.OUTPUT_EN.SetBits(1 << uint8(p))
|
||||||
case PinPWM:
|
case pinPWM:
|
||||||
sifive.GPIO0.IOF_EN.SetBits(1 << uint8(p))
|
sifive.GPIO0.IOF_EN.SetBits(1 << uint8(p))
|
||||||
sifive.GPIO0.IOF_SEL.SetBits(1 << uint8(p))
|
sifive.GPIO0.IOF_SEL.SetBits(1 << uint8(p))
|
||||||
case PinSPI:
|
case pinSPI:
|
||||||
sifive.GPIO0.IOF_EN.SetBits(1 << uint8(p))
|
sifive.GPIO0.IOF_EN.SetBits(1 << uint8(p))
|
||||||
sifive.GPIO0.IOF_SEL.ClearBits(1 << uint8(p))
|
sifive.GPIO0.IOF_SEL.ClearBits(1 << uint8(p))
|
||||||
}
|
}
|
||||||
@@ -145,9 +147,9 @@ func (spi SPI) Configure(config SPIConfig) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// enable pins for SPI
|
// enable pins for SPI
|
||||||
config.SCK.Configure(PinConfig{Mode: PinSPI})
|
config.SCK.Configure(PinConfig{Mode: pinSPI})
|
||||||
config.SDO.Configure(PinConfig{Mode: PinSPI})
|
config.SDO.Configure(PinConfig{Mode: pinSPI})
|
||||||
config.SDI.Configure(PinConfig{Mode: PinSPI})
|
config.SDI.Configure(PinConfig{Mode: pinSPI})
|
||||||
|
|
||||||
// set default frequency
|
// set default frequency
|
||||||
if config.Frequency == 0 {
|
if config.Frequency == 0 {
|
||||||
@@ -231,7 +233,7 @@ type I2CConfig struct {
|
|||||||
func (i2c *I2C) Configure(config I2CConfig) error {
|
func (i2c *I2C) Configure(config I2CConfig) error {
|
||||||
var i2cClockFrequency uint32 = 32000000
|
var i2cClockFrequency uint32 = 32000000
|
||||||
if config.Frequency == 0 {
|
if config.Frequency == 0 {
|
||||||
config.Frequency = TWI_FREQ_100KHZ
|
config.Frequency = 100 * KHz
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.SDA == 0 && config.SCL == 0 {
|
if config.SDA == 0 && config.SCL == 0 {
|
||||||
@@ -251,8 +253,8 @@ func (i2c *I2C) Configure(config I2CConfig) error {
|
|||||||
// enable controller
|
// enable controller
|
||||||
i2c.Bus.CTR.SetBits(sifive.I2C_CTR_EN)
|
i2c.Bus.CTR.SetBits(sifive.I2C_CTR_EN)
|
||||||
|
|
||||||
config.SDA.Configure(PinConfig{Mode: PinI2C})
|
config.SDA.Configure(PinConfig{Mode: pinI2C})
|
||||||
config.SCL.Configure(PinConfig{Mode: PinI2C})
|
config.SCL.Configure(PinConfig{Mode: pinI2C})
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,11 +23,17 @@ type PinChange uint8
|
|||||||
// Pin modes.
|
// Pin modes.
|
||||||
const (
|
const (
|
||||||
PinInput PinMode = iota
|
PinInput PinMode = iota
|
||||||
PinInputPullUp
|
PinInputPullup
|
||||||
PinInputPullDown
|
PinInputPulldown
|
||||||
PinOutput
|
PinOutput
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Deprecated: use PinInputPullup and PinInputPulldown instead.
|
||||||
|
const (
|
||||||
|
PinInputPullUp = PinInputPullup
|
||||||
|
PinInputPullDown = PinInputPulldown
|
||||||
|
)
|
||||||
|
|
||||||
// FPIOA internal pull resistors.
|
// FPIOA internal pull resistors.
|
||||||
const (
|
const (
|
||||||
fpioaPullNone fpioaPullMode = iota
|
fpioaPullNone fpioaPullMode = iota
|
||||||
@@ -89,10 +95,10 @@ func (p Pin) Configure(config PinConfig) {
|
|||||||
case PinInput:
|
case PinInput:
|
||||||
p.setFPIOAIOPull(fpioaPullNone)
|
p.setFPIOAIOPull(fpioaPullNone)
|
||||||
input = true
|
input = true
|
||||||
case PinInputPullUp:
|
case PinInputPullup:
|
||||||
p.setFPIOAIOPull(fpioaPullUp)
|
p.setFPIOAIOPull(fpioaPullUp)
|
||||||
input = true
|
input = true
|
||||||
case PinInputPullDown:
|
case PinInputPulldown:
|
||||||
p.setFPIOAIOPull(fpioaPullDown)
|
p.setFPIOAIOPull(fpioaPullDown)
|
||||||
input = true
|
input = true
|
||||||
case PinOutput:
|
case PinOutput:
|
||||||
@@ -517,7 +523,7 @@ type I2CConfig struct {
|
|||||||
func (i2c *I2C) Configure(config I2CConfig) error {
|
func (i2c *I2C) Configure(config I2CConfig) error {
|
||||||
|
|
||||||
if config.Frequency == 0 {
|
if config.Frequency == 0 {
|
||||||
config.Frequency = TWI_FREQ_100KHZ
|
config.Frequency = 100 * KHz
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.SDA == 0 && config.SCL == 0 {
|
if config.SDA == 0 && config.SCL == 0 {
|
||||||
|
|||||||
@@ -21,36 +21,40 @@ func CPUFrequency() uint32 {
|
|||||||
const (
|
const (
|
||||||
// GPIO
|
// GPIO
|
||||||
PinInput PinMode = iota
|
PinInput PinMode = iota
|
||||||
PinInputPullUp
|
PinInputPullup
|
||||||
PinInputPullDown
|
PinInputPulldown
|
||||||
PinOutput
|
PinOutput
|
||||||
PinOutputOpenDrain
|
PinOutputOpenDrain
|
||||||
PinDisable
|
PinDisable
|
||||||
|
|
||||||
// ADC
|
// ADC
|
||||||
PinInputAnalog
|
pinInputAnalog
|
||||||
|
|
||||||
// UART
|
// UART
|
||||||
PinModeUARTTX
|
pinModeUARTTX
|
||||||
PinModeUARTRX
|
pinModeUARTRX
|
||||||
|
|
||||||
// SPI
|
// SPI
|
||||||
PinModeSPISDI
|
pinModeSPISDI
|
||||||
PinModeSPISDO
|
pinModeSPISDO
|
||||||
PinModeSPICLK
|
pinModeSPICLK
|
||||||
PinModeSPICS
|
pinModeSPICS
|
||||||
|
|
||||||
// I2C
|
// I2C
|
||||||
PinModeI2CSDA
|
pinModeI2CSDA
|
||||||
PinModeI2CSCL
|
pinModeI2CSCL
|
||||||
|
)
|
||||||
|
|
||||||
|
// Deprecated: use PinInputPullup and PinInputPulldown instead.
|
||||||
|
const (
|
||||||
|
PinInputPullUp = PinInputPullup
|
||||||
|
PinInputPullDown = PinInputPulldown
|
||||||
)
|
)
|
||||||
|
|
||||||
type PinChange uint8
|
type PinChange uint8
|
||||||
|
|
||||||
const (
|
const (
|
||||||
PinLow PinChange = iota
|
PinRising PinChange = iota + 2
|
||||||
PinHigh
|
|
||||||
PinRising
|
|
||||||
PinFalling
|
PinFalling
|
||||||
PinToggle
|
PinToggle
|
||||||
)
|
)
|
||||||
@@ -259,11 +263,11 @@ func (p Pin) Configure(config PinConfig) {
|
|||||||
gpio.GDIR.ClearBits(p.getMask())
|
gpio.GDIR.ClearBits(p.getMask())
|
||||||
pad.Set(dse(7))
|
pad.Set(dse(7))
|
||||||
|
|
||||||
case PinInputPullUp:
|
case PinInputPullup:
|
||||||
gpio.GDIR.ClearBits(p.getMask())
|
gpio.GDIR.ClearBits(p.getMask())
|
||||||
pad.Set(dse(7) | pke | pue | pup(3) | hys)
|
pad.Set(dse(7) | pke | pue | pup(3) | hys)
|
||||||
|
|
||||||
case PinInputPullDown:
|
case PinInputPulldown:
|
||||||
gpio.GDIR.ClearBits(p.getMask())
|
gpio.GDIR.ClearBits(p.getMask())
|
||||||
pad.Set(dse(7) | pke | pue | hys)
|
pad.Set(dse(7) | pke | pue | hys)
|
||||||
|
|
||||||
@@ -279,29 +283,29 @@ func (p Pin) Configure(config PinConfig) {
|
|||||||
gpio.GDIR.ClearBits(p.getMask())
|
gpio.GDIR.ClearBits(p.getMask())
|
||||||
pad.Set(dse(7) | hys)
|
pad.Set(dse(7) | hys)
|
||||||
|
|
||||||
case PinInputAnalog:
|
case pinInputAnalog:
|
||||||
gpio.GDIR.ClearBits(p.getMask())
|
gpio.GDIR.ClearBits(p.getMask())
|
||||||
pad.Set(dse(7))
|
pad.Set(dse(7))
|
||||||
|
|
||||||
case PinModeUARTTX:
|
case pinModeUARTTX:
|
||||||
pad.Set(sre | dse(3) | spd(3))
|
pad.Set(sre | dse(3) | spd(3))
|
||||||
|
|
||||||
case PinModeUARTRX:
|
case pinModeUARTRX:
|
||||||
pad.Set(dse(7) | pke | pue | pup(3) | hys)
|
pad.Set(dse(7) | pke | pue | pup(3) | hys)
|
||||||
|
|
||||||
case PinModeSPISDI:
|
case pinModeSPISDI:
|
||||||
pad.Set(dse(7) | spd(2))
|
pad.Set(dse(7) | spd(2))
|
||||||
|
|
||||||
case PinModeSPISDO:
|
case pinModeSPISDO:
|
||||||
pad.Set(dse(7) | spd(2))
|
pad.Set(dse(7) | spd(2))
|
||||||
|
|
||||||
case PinModeSPICLK:
|
case pinModeSPICLK:
|
||||||
pad.Set(dse(7) | spd(2))
|
pad.Set(dse(7) | spd(2))
|
||||||
|
|
||||||
case PinModeSPICS:
|
case pinModeSPICS:
|
||||||
pad.Set(dse(7))
|
pad.Set(dse(7))
|
||||||
|
|
||||||
case PinModeI2CSDA, PinModeI2CSCL:
|
case pinModeI2CSDA, pinModeI2CSCL:
|
||||||
pad.Set(ode | sre | dse(4) | spd(1) | pke | pue | pup(3))
|
pad.Set(ode | sre | dse(4) | spd(1) | pke | pue | pup(3))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -387,7 +391,7 @@ func (p Pin) SetInterrupt(change PinChange, callback func(Pin)) error {
|
|||||||
mask := p.getMask()
|
mask := p.getMask()
|
||||||
if nil != callback {
|
if nil != callback {
|
||||||
switch change {
|
switch change {
|
||||||
case PinLow, PinHigh, PinRising, PinFalling:
|
case PinRising, PinFalling:
|
||||||
gpio.EDGE_SEL.ClearBits(mask)
|
gpio.EDGE_SEL.ClearBits(mask)
|
||||||
var reg *volatile.Register32
|
var reg *volatile.Register32
|
||||||
var pos uint8
|
var pos uint8
|
||||||
@@ -746,7 +750,7 @@ func (p Pin) getMuxMode(config PinConfig) uint32 {
|
|||||||
switch config.Mode {
|
switch config.Mode {
|
||||||
|
|
||||||
// GPIO
|
// GPIO
|
||||||
case PinInput, PinInputPullUp, PinInputPullDown,
|
case PinInput, PinInputPullup, PinInputPulldown,
|
||||||
PinOutput, PinOutputOpenDrain, PinDisable:
|
PinOutput, PinOutputOpenDrain, PinDisable:
|
||||||
mode := uint32(0x5) // GPIO is always alternate function 5
|
mode := uint32(0x5) // GPIO is always alternate function 5
|
||||||
if forcePath {
|
if forcePath {
|
||||||
@@ -755,7 +759,7 @@ func (p Pin) getMuxMode(config PinConfig) uint32 {
|
|||||||
return mode
|
return mode
|
||||||
|
|
||||||
// ADC
|
// ADC
|
||||||
case PinInputAnalog:
|
case pinInputAnalog:
|
||||||
mode := uint32(0x5) // use alternate function 5 (GPIO)
|
mode := uint32(0x5) // use alternate function 5 (GPIO)
|
||||||
if forcePath {
|
if forcePath {
|
||||||
mode |= 0x10 // SION bit
|
mode |= 0x10 // SION bit
|
||||||
@@ -763,7 +767,7 @@ func (p Pin) getMuxMode(config PinConfig) uint32 {
|
|||||||
return mode
|
return mode
|
||||||
|
|
||||||
// UART RX/TX
|
// UART RX/TX
|
||||||
case PinModeUARTRX, PinModeUARTTX:
|
case pinModeUARTRX, pinModeUARTTX:
|
||||||
mode := uint32(0x2) // UART is usually alternate function 2 on Teensy 4.x
|
mode := uint32(0x2) // UART is usually alternate function 2 on Teensy 4.x
|
||||||
// Teensy 4.1 has a UART (LPUART5) with alternate function 1
|
// Teensy 4.1 has a UART (LPUART5) with alternate function 1
|
||||||
if p == PB28 || p == PB29 {
|
if p == PB28 || p == PB29 {
|
||||||
@@ -772,7 +776,7 @@ func (p Pin) getMuxMode(config PinConfig) uint32 {
|
|||||||
return mode
|
return mode
|
||||||
|
|
||||||
// SPI SDI
|
// SPI SDI
|
||||||
case PinModeSPISDI:
|
case pinModeSPISDI:
|
||||||
var mode uint32
|
var mode uint32
|
||||||
switch p {
|
switch p {
|
||||||
case PC15: // LPSPI1 SDI on PC15 alternate function 4
|
case PC15: // LPSPI1 SDI on PC15 alternate function 4
|
||||||
@@ -790,7 +794,7 @@ func (p Pin) getMuxMode(config PinConfig) uint32 {
|
|||||||
return mode
|
return mode
|
||||||
|
|
||||||
// SPI SDO
|
// SPI SDO
|
||||||
case PinModeSPISDO:
|
case pinModeSPISDO:
|
||||||
var mode uint32
|
var mode uint32
|
||||||
switch p {
|
switch p {
|
||||||
case PC14: // LPSPI1 SDO on PC14 alternate function 4
|
case PC14: // LPSPI1 SDO on PC14 alternate function 4
|
||||||
@@ -808,7 +812,7 @@ func (p Pin) getMuxMode(config PinConfig) uint32 {
|
|||||||
return mode
|
return mode
|
||||||
|
|
||||||
// SPI SCK
|
// SPI SCK
|
||||||
case PinModeSPICLK:
|
case pinModeSPICLK:
|
||||||
var mode uint32
|
var mode uint32
|
||||||
switch p {
|
switch p {
|
||||||
case PC12: // LPSPI1 SCK on PC12 alternate function 4
|
case PC12: // LPSPI1 SCK on PC12 alternate function 4
|
||||||
@@ -826,7 +830,7 @@ func (p Pin) getMuxMode(config PinConfig) uint32 {
|
|||||||
return mode
|
return mode
|
||||||
|
|
||||||
// SPI CS
|
// SPI CS
|
||||||
case PinModeSPICS:
|
case pinModeSPICS:
|
||||||
var mode uint32
|
var mode uint32
|
||||||
switch p {
|
switch p {
|
||||||
case PC13: // LPSPI1 CS on PC13 alternate function 4
|
case PC13: // LPSPI1 CS on PC13 alternate function 4
|
||||||
@@ -844,7 +848,7 @@ func (p Pin) getMuxMode(config PinConfig) uint32 {
|
|||||||
return mode
|
return mode
|
||||||
|
|
||||||
// I2C SDA
|
// I2C SDA
|
||||||
case PinModeI2CSDA:
|
case pinModeI2CSDA:
|
||||||
var mode uint32
|
var mode uint32
|
||||||
switch p {
|
switch p {
|
||||||
case PA13: // LPI2C4 SDA on PA13 alternate function 0
|
case PA13: // LPI2C4 SDA on PA13 alternate function 0
|
||||||
@@ -862,7 +866,7 @@ func (p Pin) getMuxMode(config PinConfig) uint32 {
|
|||||||
return mode
|
return mode
|
||||||
|
|
||||||
// I2C SCL
|
// I2C SCL
|
||||||
case PinModeI2CSCL:
|
case pinModeI2CSCL:
|
||||||
var mode uint32
|
var mode uint32
|
||||||
switch p {
|
switch p {
|
||||||
case PA12: // LPI2C4 SCL on PA12 alternate function 0
|
case PA12: // LPI2C4 SCL on PA12 alternate function 0
|
||||||
@@ -898,7 +902,7 @@ func (a ADC) Configure(config ADCConfig) {
|
|||||||
defaultSamples = uint32(4)
|
defaultSamples = uint32(4)
|
||||||
)
|
)
|
||||||
|
|
||||||
a.Pin.Configure(PinConfig{Mode: PinInputAnalog})
|
a.Pin.Configure(PinConfig{Mode: pinInputAnalog})
|
||||||
|
|
||||||
resolution, samples := config.Resolution, config.Samples
|
resolution, samples := config.Resolution, config.Samples
|
||||||
if 0 == resolution {
|
if 0 == resolution {
|
||||||
|
|||||||
@@ -10,15 +10,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
TWI_FREQ_BUS = 24000000 // LPI2C root clock is on 24 MHz OSC
|
|
||||||
TWI_FREQ_100KHZ = 100000 // StandardMode (100 kHz)
|
|
||||||
TWI_FREQ_400KHZ = 400000 // FastMode (400 kHz)
|
|
||||||
TWI_FREQ_1MHZ = 1000000 // FastModePlus (1 MHz)
|
|
||||||
TWI_FREQ_5MHZ = 5000000 // UltraFastMode (5 MHz)
|
|
||||||
TWI_FREQ_DEFAULT = TWI_FREQ_100KHZ // default to StandardMode (100 kHz)
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
errI2CWriteTimeout = errors.New("I2C timeout during write")
|
errI2CWriteTimeout = errors.New("I2C timeout during write")
|
||||||
errI2CReadTimeout = errors.New("I2C timeout during read")
|
errI2CReadTimeout = errors.New("I2C timeout during read")
|
||||||
@@ -165,8 +156,8 @@ func (i2c *I2C) Configure(config I2CConfig) {
|
|||||||
sda, scl := i2c.setPins(config)
|
sda, scl := i2c.setPins(config)
|
||||||
|
|
||||||
// configure the mux and pad control registers
|
// configure the mux and pad control registers
|
||||||
sda.Configure(PinConfig{Mode: PinModeI2CSDA})
|
sda.Configure(PinConfig{Mode: pinModeI2CSDA})
|
||||||
scl.Configure(PinConfig{Mode: PinModeI2CSCL})
|
scl.Configure(PinConfig{Mode: pinModeI2CSCL})
|
||||||
|
|
||||||
// configure the mux input selector
|
// configure the mux input selector
|
||||||
i2c.muxSDA.connect()
|
i2c.muxSDA.connect()
|
||||||
@@ -174,7 +165,7 @@ func (i2c *I2C) Configure(config I2CConfig) {
|
|||||||
|
|
||||||
freq := config.Frequency
|
freq := config.Frequency
|
||||||
if 0 == freq {
|
if 0 == freq {
|
||||||
freq = TWI_FREQ_DEFAULT
|
freq = 100 * KHz
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset clock and registers, and enable LPI2C module interface
|
// reset clock and registers, and enable LPI2C module interface
|
||||||
@@ -305,7 +296,7 @@ func (i2c *I2C) setFrequency(freq uint32) {
|
|||||||
wasEnabled := i2c.Bus.MCR.HasBits(nxp.LPI2C_MCR_MEN)
|
wasEnabled := i2c.Bus.MCR.HasBits(nxp.LPI2C_MCR_MEN)
|
||||||
i2c.Bus.MCR.ClearBits(nxp.LPI2C_MCR_MEN)
|
i2c.Bus.MCR.ClearBits(nxp.LPI2C_MCR_MEN)
|
||||||
|
|
||||||
// baud rate = (TWI_FREQ_BUS/(2^pre))/(CLKLO+1 + CLKHI+1 + FLOOR((2+FILTSCL)/(2^pre)))
|
// baud rate = (24MHz/(2^pre))/(CLKLO+1 + CLKHI+1 + FLOOR((2+FILTSCL)/(2^pre)))
|
||||||
// assume: CLKLO=2*CLKHI, SETHOLD=CLKHI, DATAVD=CLKHI/2
|
// assume: CLKLO=2*CLKHI, SETHOLD=CLKHI, DATAVD=CLKHI/2
|
||||||
for pre := uint32(1); pre <= 128; pre *= 2 {
|
for pre := uint32(1); pre <= 128; pre *= 2 {
|
||||||
if bestError == 0 {
|
if bestError == 0 {
|
||||||
@@ -314,9 +305,9 @@ func (i2c *I2C) setFrequency(freq uint32) {
|
|||||||
for clkHi := uint32(1); clkHi < 32; clkHi++ {
|
for clkHi := uint32(1); clkHi < 32; clkHi++ {
|
||||||
var absError, rate uint32
|
var absError, rate uint32
|
||||||
if clkHi == 1 {
|
if clkHi == 1 {
|
||||||
rate = (TWI_FREQ_BUS / pre) / (1 + 3 + 2 + 2/pre)
|
rate = (24 * MHz / pre) / (1 + 3 + 2 + 2/pre)
|
||||||
} else {
|
} else {
|
||||||
rate = (TWI_FREQ_BUS / pre) / (3*clkHi + 2 + 2/pre)
|
rate = (24 * MHz / pre) / (3*clkHi + 2 + 2/pre)
|
||||||
}
|
}
|
||||||
if freq > rate {
|
if freq > rate {
|
||||||
absError = freq - rate
|
absError = freq - rate
|
||||||
@@ -370,15 +361,15 @@ func (i2c *I2C) setFrequency(freq uint32) {
|
|||||||
mcfgr2, mcfgr3 uint32
|
mcfgr2, mcfgr3 uint32
|
||||||
)
|
)
|
||||||
const i2cClockStretchTimeout = 15000 // microseconds
|
const i2cClockStretchTimeout = 15000 // microseconds
|
||||||
if freq >= TWI_FREQ_5MHZ {
|
if freq >= 5*MHz {
|
||||||
// I2C UltraFastMode 5 MHz
|
// I2C UltraFastMode 5 MHz
|
||||||
mcfgr2 = 0 // disable glitch filters and timeout for UltraFastMode
|
mcfgr2 = 0 // disable glitch filters and timeout for UltraFastMode
|
||||||
mcfgr3 = 0 //
|
mcfgr3 = 0 //
|
||||||
} else if freq >= TWI_FREQ_1MHZ {
|
} else if freq >= 1*MHz {
|
||||||
// I2C FastModePlus 1 MHz
|
// I2C FastModePlus 1 MHz
|
||||||
mcfgr2 = filtsda(1) | filtscl(1) | busidle(2400) // 100us timeout
|
mcfgr2 = filtsda(1) | filtscl(1) | busidle(2400) // 100us timeout
|
||||||
mcfgr3 = pinlow(i2cClockStretchTimeout*24/256 + 1)
|
mcfgr3 = pinlow(i2cClockStretchTimeout*24/256 + 1)
|
||||||
} else if freq >= TWI_FREQ_400KHZ {
|
} else if freq >= 400*KHz {
|
||||||
// I2C FastMode 400 kHz
|
// I2C FastMode 400 kHz
|
||||||
mcfgr2 = filtsda(2) | filtscl(2) | busidle(3600) // 150us timeout
|
mcfgr2 = filtsda(2) | filtscl(2) | busidle(3600) // 150us timeout
|
||||||
mcfgr3 = pinlow(i2cClockStretchTimeout*24/256 + 1)
|
mcfgr3 = pinlow(i2cClockStretchTimeout*24/256 + 1)
|
||||||
|
|||||||
@@ -77,10 +77,10 @@ func (spi *SPI) Configure(config SPIConfig) {
|
|||||||
spi.sdi, spi.sdo, spi.sck, spi.cs = config.getPins()
|
spi.sdi, spi.sdo, spi.sck, spi.cs = config.getPins()
|
||||||
|
|
||||||
// configure the mux and pad control registers
|
// configure the mux and pad control registers
|
||||||
spi.sdi.Configure(PinConfig{Mode: PinModeSPISDI})
|
spi.sdi.Configure(PinConfig{Mode: pinModeSPISDI})
|
||||||
spi.sdo.Configure(PinConfig{Mode: PinModeSPISDO})
|
spi.sdo.Configure(PinConfig{Mode: pinModeSPISDO})
|
||||||
spi.sck.Configure(PinConfig{Mode: PinModeSPICLK})
|
spi.sck.Configure(PinConfig{Mode: pinModeSPICLK})
|
||||||
spi.cs.Configure(PinConfig{Mode: PinModeSPICS})
|
spi.cs.Configure(PinConfig{Mode: pinModeSPICS})
|
||||||
|
|
||||||
// configure the mux input selector
|
// configure the mux input selector
|
||||||
spi.muxSDI.connect()
|
spi.muxSDI.connect()
|
||||||
|
|||||||
@@ -68,8 +68,8 @@ func (uart *UART) Configure(config UARTConfig) {
|
|||||||
uart.tx = config.TX
|
uart.tx = config.TX
|
||||||
|
|
||||||
// configure the mux and pad control registers
|
// configure the mux and pad control registers
|
||||||
uart.rx.Configure(PinConfig{Mode: PinModeUARTRX})
|
uart.rx.Configure(PinConfig{Mode: pinModeUARTRX})
|
||||||
uart.tx.Configure(PinConfig{Mode: PinModeUARTTX})
|
uart.tx.Configure(PinConfig{Mode: pinModeUARTTX})
|
||||||
|
|
||||||
// configure the mux input selector
|
// configure the mux input selector
|
||||||
uart.muxRX.connect()
|
uart.muxRX.connect()
|
||||||
@@ -159,8 +159,8 @@ func (uart *UART) Disable() {
|
|||||||
uart.Bus.CTRL.ClearBits(nxp.LPUART_CTRL_TE | nxp.LPUART_CTRL_RE)
|
uart.Bus.CTRL.ClearBits(nxp.LPUART_CTRL_TE | nxp.LPUART_CTRL_RE)
|
||||||
|
|
||||||
// put pins back into GPIO mode
|
// put pins back into GPIO mode
|
||||||
uart.rx.Configure(PinConfig{Mode: PinInputPullUp})
|
uart.rx.Configure(PinConfig{Mode: PinInputPullup})
|
||||||
uart.tx.Configure(PinConfig{Mode: PinInputPullUp})
|
uart.tx.Configure(PinConfig{Mode: PinInputPullup})
|
||||||
}
|
}
|
||||||
uart.configured = false
|
uart.configured = false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,15 +5,10 @@ package machine
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"device/nrf"
|
"device/nrf"
|
||||||
"errors"
|
|
||||||
"runtime/interrupt"
|
"runtime/interrupt"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
ErrTxInvalidSliceSize = errors.New("SPI write and read slices must be same size")
|
|
||||||
)
|
|
||||||
|
|
||||||
const deviceName = nrf.Device
|
const deviceName = nrf.Device
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -230,7 +225,7 @@ func (i2c *I2C) Configure(config I2CConfig) error {
|
|||||||
|
|
||||||
// Default I2C bus speed is 100 kHz.
|
// Default I2C bus speed is 100 kHz.
|
||||||
if config.Frequency == 0 {
|
if config.Frequency == 0 {
|
||||||
config.Frequency = TWI_FREQ_100KHZ
|
config.Frequency = 100 * KHz
|
||||||
}
|
}
|
||||||
// Default I2C pins if not set.
|
// Default I2C pins if not set.
|
||||||
if config.SDA == 0 && config.SCL == 0 {
|
if config.SDA == 0 && config.SCL == 0 {
|
||||||
@@ -253,7 +248,7 @@ func (i2c *I2C) Configure(config I2CConfig) error {
|
|||||||
(nrf.GPIO_PIN_CNF_DRIVE_S0D1 << nrf.GPIO_PIN_CNF_DRIVE_Pos) |
|
(nrf.GPIO_PIN_CNF_DRIVE_S0D1 << nrf.GPIO_PIN_CNF_DRIVE_Pos) |
|
||||||
(nrf.GPIO_PIN_CNF_SENSE_Disabled << nrf.GPIO_PIN_CNF_SENSE_Pos))
|
(nrf.GPIO_PIN_CNF_SENSE_Disabled << nrf.GPIO_PIN_CNF_SENSE_Pos))
|
||||||
|
|
||||||
if config.Frequency == TWI_FREQ_400KHZ {
|
if config.Frequency >= 400*KHz {
|
||||||
i2c.Bus.FREQUENCY.Set(nrf.TWI_FREQUENCY_FREQUENCY_K400)
|
i2c.Bus.FREQUENCY.Set(nrf.TWI_FREQUENCY_FREQUENCY_K400)
|
||||||
} else {
|
} else {
|
||||||
i2c.Bus.FREQUENCY.Set(nrf.TWI_FREQUENCY_FREQUENCY_K100)
|
i2c.Bus.FREQUENCY.Set(nrf.TWI_FREQUENCY_FREQUENCY_K100)
|
||||||
@@ -350,3 +345,41 @@ func (i2c *I2C) readByte() (byte, error) {
|
|||||||
i2c.Bus.EVENTS_RXDREADY.Set(0)
|
i2c.Bus.EVENTS_RXDREADY.Set(0)
|
||||||
return byte(i2c.Bus.RXD.Get()), nil
|
return byte(i2c.Bus.RXD.Get()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var rngStarted = false
|
||||||
|
|
||||||
|
// GetRNG returns 32 bits of non-deterministic random data based on internal thermal noise.
|
||||||
|
// According to Nordic's documentation, the random output is suitable for cryptographic purposes.
|
||||||
|
func GetRNG() (ret uint32, err error) {
|
||||||
|
// There's no apparent way to check the status of the RNG peripheral's task, so simply start it
|
||||||
|
// to avoid deadlocking while waiting for output.
|
||||||
|
if !rngStarted {
|
||||||
|
nrf.RNG.TASKS_START.Set(1)
|
||||||
|
nrf.RNG.SetCONFIG_DERCEN(nrf.RNG_CONFIG_DERCEN_Enabled)
|
||||||
|
rngStarted = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// The RNG returns one byte at a time, so stack up four bytes into a single uint32 for return.
|
||||||
|
for i := 0; i < 4; i++ {
|
||||||
|
// Wait for data to be ready.
|
||||||
|
for nrf.RNG.EVENTS_VALRDY.Get() == 0 {
|
||||||
|
}
|
||||||
|
// Append random byte to output.
|
||||||
|
ret = (ret << 8) ^ nrf.RNG.GetVALUE()
|
||||||
|
// Unset the EVENTS_VALRDY register to avoid reading the same random output twice.
|
||||||
|
nrf.RNG.EVENTS_VALRDY.Set(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadTemperature reads the silicon die temperature of the chip. The return
|
||||||
|
// value is in milli-celsius.
|
||||||
|
func ReadTemperature() int32 {
|
||||||
|
nrf.TEMP.TASKS_START.Set(1)
|
||||||
|
for nrf.TEMP.EVENTS_DATARDY.Get() == 0 {
|
||||||
|
}
|
||||||
|
temp := int32(nrf.TEMP.TEMP.Get()) * 250 // the returned value is in units of 0.25°C
|
||||||
|
nrf.TEMP.EVENTS_DATARDY.Set(0)
|
||||||
|
return temp
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,16 +9,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
DFU_MAGIC_SERIAL_ONLY_RESET = 0x4e
|
dfuMagicSerialOnlyReset = 0x4e
|
||||||
DFU_MAGIC_UF2_RESET = 0x57
|
dfuMagicUF2Reset = 0x57
|
||||||
DFU_MAGIC_OTA_RESET = 0xA8
|
dfuMagicOTAReset = 0xA8
|
||||||
)
|
)
|
||||||
|
|
||||||
// EnterSerialBootloader resets the chip into the serial bootloader. After
|
// EnterSerialBootloader resets the chip into the serial bootloader. After
|
||||||
// reset, it can be flashed using serial/nrfutil.
|
// reset, it can be flashed using serial/nrfutil.
|
||||||
func EnterSerialBootloader() {
|
func EnterSerialBootloader() {
|
||||||
arm.DisableInterrupts()
|
arm.DisableInterrupts()
|
||||||
nrf.POWER.GPREGRET.Set(DFU_MAGIC_SERIAL_ONLY_RESET)
|
nrf.POWER.GPREGRET.Set(dfuMagicSerialOnlyReset)
|
||||||
arm.SystemReset()
|
arm.SystemReset()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ func EnterSerialBootloader() {
|
|||||||
// can be flashed via nrfutil or by copying a UF2 file to the mass storage device
|
// can be flashed via nrfutil or by copying a UF2 file to the mass storage device
|
||||||
func EnterUF2Bootloader() {
|
func EnterUF2Bootloader() {
|
||||||
arm.DisableInterrupts()
|
arm.DisableInterrupts()
|
||||||
nrf.POWER.GPREGRET.Set(DFU_MAGIC_UF2_RESET)
|
nrf.POWER.GPREGRET.Set(dfuMagicUF2Reset)
|
||||||
arm.SystemReset()
|
arm.SystemReset()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,6 +34,6 @@ func EnterUF2Bootloader() {
|
|||||||
// flashed via an OTA update
|
// flashed via an OTA update
|
||||||
func EnterOTABootloader() {
|
func EnterOTABootloader() {
|
||||||
arm.DisableInterrupts()
|
arm.DisableInterrupts()
|
||||||
nrf.POWER.GPREGRET.Set(DFU_MAGIC_OTA_RESET)
|
nrf.POWER.GPREGRET.Set(dfuMagicOTAReset)
|
||||||
arm.SystemReset()
|
arm.SystemReset()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,60 +0,0 @@
|
|||||||
//go:build nrf52840
|
|
||||||
// +build nrf52840
|
|
||||||
|
|
||||||
package machine
|
|
||||||
|
|
||||||
import (
|
|
||||||
"device/nrf"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Implementation based on Nordic Semiconductor's nRF52840 documentation version 1.7 found here:
|
|
||||||
// https://infocenter.nordicsemi.com/pdf/nRF52840_PS_v1.7.pdf
|
|
||||||
|
|
||||||
// SetRNGBiasCorrection configures the RNG peripheral's bias correction mechanism. Note that when
|
|
||||||
// bias correction is enabled, the peripheral is slower to produce random values.
|
|
||||||
func SetRNGBiasCorrection(enabled bool) {
|
|
||||||
var val uint32
|
|
||||||
if enabled {
|
|
||||||
val = nrf.RNG_CONFIG_DERCEN_Enabled
|
|
||||||
}
|
|
||||||
nrf.RNG.SetCONFIG_DERCEN(val)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RNGBiasCorrectionEnabled determines whether the RNG peripheral's bias correction mechanism is
|
|
||||||
// enabled or not.
|
|
||||||
func RNGBiasCorrectionEnabled() bool {
|
|
||||||
return nrf.RNG.GetCONFIG_DERCEN() == nrf.RNG_CONFIG_DERCEN_Enabled
|
|
||||||
}
|
|
||||||
|
|
||||||
// StartRNG starts the RNG peripheral core. This is automatically called by GetRNG, but can be
|
|
||||||
// manually called for interacting with the RNG peripheral directly.
|
|
||||||
func StartRNG() {
|
|
||||||
nrf.RNG.SetTASKS_START(nrf.RNG_TASKS_START_TASKS_START_Trigger)
|
|
||||||
}
|
|
||||||
|
|
||||||
// StopRNG stops the RNG peripheral core. This is not called automatically. It may make sense to
|
|
||||||
// manually disable RNG peripheral for power conservation.
|
|
||||||
func StopRNG() {
|
|
||||||
nrf.RNG.SetTASKS_STOP(nrf.RNG_TASKS_STOP_TASKS_STOP_Trigger)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetRNG returns 32 bits of non-deterministic random data based on internal thermal noise.
|
|
||||||
// According to Nordic's documentation, the random output is suitable for cryptographic purposes.
|
|
||||||
func GetRNG() (ret uint32, err error) {
|
|
||||||
// There's no apparent way to check the status of the RNG peripheral's task, so simply start it
|
|
||||||
// to avoid deadlocking while waiting for output.
|
|
||||||
StartRNG()
|
|
||||||
|
|
||||||
// The RNG returns one byte at a time, so stack up four bytes into a single uint32 for return.
|
|
||||||
for i := 0; i < 4; i++ {
|
|
||||||
// Wait for data to be ready.
|
|
||||||
for nrf.RNG.GetEVENTS_VALRDY() == nrf.RNG_EVENTS_VALRDY_EVENTS_VALRDY_NotGenerated {
|
|
||||||
}
|
|
||||||
// Append random byte to output.
|
|
||||||
ret = (ret << 8) ^ nrf.RNG.GetVALUE()
|
|
||||||
// Unset the EVENTS_VALRDY register to avoid reading the same random output twice.
|
|
||||||
nrf.RNG.SetEVENTS_VALRDY(nrf.RNG_EVENTS_VALRDY_EVENTS_VALRDY_NotGenerated)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
@@ -42,13 +42,19 @@ const deviceName = nxp.Device
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
PinInput PinMode = iota
|
PinInput PinMode = iota
|
||||||
PinInputPullUp
|
PinInputPullup
|
||||||
PinInputPullDown
|
PinInputPulldown
|
||||||
PinOutput
|
PinOutput
|
||||||
PinOutputOpenDrain
|
PinOutputOpenDrain
|
||||||
PinDisable
|
PinDisable
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Deprecated: use PinInputPullup and PinInputPulldown instead.
|
||||||
|
const (
|
||||||
|
PinInputPullUp = PinInputPullup
|
||||||
|
PinInputPullDown = PinInputPulldown
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
PA00 Pin = iota
|
PA00 Pin = iota
|
||||||
PA01
|
PA01
|
||||||
@@ -223,11 +229,11 @@ func (p Pin) Configure(config PinConfig) {
|
|||||||
gpio.PDDR.ClearBits(1 << pos)
|
gpio.PDDR.ClearBits(1 << pos)
|
||||||
pcr.Set((1 << nxp.PORT_PCR0_MUX_Pos))
|
pcr.Set((1 << nxp.PORT_PCR0_MUX_Pos))
|
||||||
|
|
||||||
case PinInputPullUp:
|
case PinInputPullup:
|
||||||
gpio.PDDR.ClearBits(1 << pos)
|
gpio.PDDR.ClearBits(1 << pos)
|
||||||
pcr.Set((1 << nxp.PORT_PCR0_MUX_Pos) | nxp.PORT_PCR0_PE | nxp.PORT_PCR0_PS)
|
pcr.Set((1 << nxp.PORT_PCR0_MUX_Pos) | nxp.PORT_PCR0_PE | nxp.PORT_PCR0_PS)
|
||||||
|
|
||||||
case PinInputPullDown:
|
case PinInputPulldown:
|
||||||
gpio.PDDR.ClearBits(1 << pos)
|
gpio.PDDR.ClearBits(1 << pos)
|
||||||
pcr.Set((1 << nxp.PORT_PCR0_MUX_Pos) | nxp.PORT_PCR0_PE)
|
pcr.Set((1 << nxp.PORT_PCR0_MUX_Pos) | nxp.PORT_PCR0_PE)
|
||||||
|
|
||||||
|
|||||||
@@ -203,8 +203,8 @@ func (u *UART) Disable() {
|
|||||||
u.C2.Set(0)
|
u.C2.Set(0)
|
||||||
|
|
||||||
// reconfigure pin
|
// reconfigure pin
|
||||||
u.DefaultRX.Configure(PinConfig{Mode: PinInputPullUp})
|
u.DefaultRX.Configure(PinConfig{Mode: PinInputPullup})
|
||||||
u.DefaultTX.Configure(PinConfig{Mode: PinInputPullUp})
|
u.DefaultTX.Configure(PinConfig{Mode: PinInputPullup})
|
||||||
|
|
||||||
// clear flags
|
// clear flags
|
||||||
u.S1.Get()
|
u.S1.Get()
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ const (
|
|||||||
adc0_CH ADCChannel = iota
|
adc0_CH ADCChannel = iota
|
||||||
adc1_CH
|
adc1_CH
|
||||||
adc2_CH
|
adc2_CH
|
||||||
adc3_CH // Note: GPIO29 not broken out on pico board
|
adc3_CH // Note: GPIO29 not broken out on pico board
|
||||||
ADC_TEMP_SENSOR // Internal temperature sensor channel
|
adcTempSensor // Internal temperature sensor channel
|
||||||
)
|
)
|
||||||
|
|
||||||
// Used to serialise ADC sampling
|
// Used to serialise ADC sampling
|
||||||
@@ -75,19 +75,17 @@ func (a ADC) GetADCChannel() (c ADCChannel, err error) {
|
|||||||
return c, err
|
return c, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure sets the channel's associated pin to analog input mode or powers on the temperature sensor for ADC_TEMP_SENSOR.
|
// Configure sets the channel's associated pin to analog input mode.
|
||||||
// The powered on temperature sensor increases ADC_AVDD current by approximately 40 μA.
|
// The powered on temperature sensor increases ADC_AVDD current by approximately 40 μA.
|
||||||
func (c ADCChannel) Configure(config ADCConfig) error {
|
func (c ADCChannel) Configure(config ADCConfig) error {
|
||||||
if config.Reference != 0 {
|
if config.Reference != 0 {
|
||||||
adcAref = config.Reference
|
adcAref = config.Reference
|
||||||
}
|
}
|
||||||
if p, err := c.Pin(); err == nil {
|
p, err := c.Pin()
|
||||||
p.Configure(PinConfig{Mode: PinAnalog})
|
if err != nil {
|
||||||
}
|
return err
|
||||||
if c == ADC_TEMP_SENSOR {
|
|
||||||
// Enable temperature sensor bias source
|
|
||||||
rp.ADC.CS.SetBits(rp.ADC_CS_TS_EN)
|
|
||||||
}
|
}
|
||||||
|
p.Configure(PinConfig{Mode: pinAnalog})
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,13 +110,16 @@ func (c ADCChannel) getVoltage() uint32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ReadTemperature does a one-shot sample of the internal temperature sensor and returns a milli-celsius reading.
|
// ReadTemperature does a one-shot sample of the internal temperature sensor and returns a milli-celsius reading.
|
||||||
// Only works on the ADC_TEMP_SENSOR channel. aka AINSEL=4. Other channels will return 0
|
func ReadTemperature() (millicelsius int32) {
|
||||||
func (c ADCChannel) ReadTemperature() (millicelsius uint32) {
|
if rp.ADC.CS.Get()&rp.ADC_CS_EN == 0 {
|
||||||
if c != ADC_TEMP_SENSOR {
|
InitADC()
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Enable temperature sensor bias source
|
||||||
|
rp.ADC.CS.SetBits(rp.ADC_CS_TS_EN)
|
||||||
|
|
||||||
// T = 27 - (ADC_voltage - 0.706)/0.001721
|
// T = 27 - (ADC_voltage - 0.706)/0.001721
|
||||||
return (27000<<16 - (c.getVoltage()-706<<16)*581) >> 16
|
return (27000<<16 - (int32(adcTempSensor.getVoltage())-706<<16)*581) >> 16
|
||||||
}
|
}
|
||||||
|
|
||||||
// waitForReady spins waiting for the ADC peripheral to become ready.
|
// waitForReady spins waiting for the ADC peripheral to become ready.
|
||||||
|
|||||||
@@ -10,11 +10,6 @@ import (
|
|||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
KHz = 1000
|
|
||||||
MHz = 1000000
|
|
||||||
)
|
|
||||||
|
|
||||||
func CPUFrequency() uint32 {
|
func CPUFrequency() uint32 {
|
||||||
return 125 * MHz
|
return 125 * MHz
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,11 +81,13 @@ const (
|
|||||||
PinInput
|
PinInput
|
||||||
PinInputPulldown
|
PinInputPulldown
|
||||||
PinInputPullup
|
PinInputPullup
|
||||||
PinAnalog
|
|
||||||
PinUART
|
// internal pin modes
|
||||||
PinPWM
|
pinAnalog
|
||||||
PinI2C
|
pinUART
|
||||||
PinSPI
|
pinPWM
|
||||||
|
pinI2C
|
||||||
|
pinSPI
|
||||||
)
|
)
|
||||||
|
|
||||||
func (p Pin) PortMaskSet() (*uint32, uint32) {
|
func (p Pin) PortMaskSet() (*uint32, uint32) {
|
||||||
@@ -188,20 +190,20 @@ func (p Pin) Configure(config PinConfig) {
|
|||||||
case PinInputPullup:
|
case PinInputPullup:
|
||||||
p.setFunc(fnSIO)
|
p.setFunc(fnSIO)
|
||||||
p.pullup()
|
p.pullup()
|
||||||
case PinAnalog:
|
case pinAnalog:
|
||||||
p.setFunc(fnNULL)
|
p.setFunc(fnNULL)
|
||||||
p.pulloff()
|
p.pulloff()
|
||||||
case PinUART:
|
case pinUART:
|
||||||
p.setFunc(fnUART)
|
p.setFunc(fnUART)
|
||||||
case PinPWM:
|
case pinPWM:
|
||||||
p.setFunc(fnPWM)
|
p.setFunc(fnPWM)
|
||||||
case PinI2C:
|
case pinI2C:
|
||||||
// IO config according to 4.3.1.3 of rp2040 datasheet.
|
// IO config according to 4.3.1.3 of rp2040 datasheet.
|
||||||
p.setFunc(fnI2C)
|
p.setFunc(fnI2C)
|
||||||
p.pullup()
|
p.pullup()
|
||||||
p.setSchmitt(true)
|
p.setSchmitt(true)
|
||||||
p.setSlew(false)
|
p.setSlew(false)
|
||||||
case PinSPI:
|
case pinSPI:
|
||||||
p.setFunc(fnSPI)
|
p.setFunc(fnSPI)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -226,12 +228,8 @@ type PinChange uint8
|
|||||||
|
|
||||||
// Pin change interrupt constants for SetInterrupt.
|
// Pin change interrupt constants for SetInterrupt.
|
||||||
const (
|
const (
|
||||||
// PinLevelLow triggers whenever pin is at a low (around 0V) logic level.
|
|
||||||
PinLevelLow PinChange = 1 << iota
|
|
||||||
// PinLevelLow triggers whenever pin is at a high (around 3V) logic level.
|
|
||||||
PinLevelHigh
|
|
||||||
// Edge falling
|
// Edge falling
|
||||||
PinFalling
|
PinFalling PinChange = 4 << iota
|
||||||
// Edge rising
|
// Edge rising
|
||||||
PinRising
|
PinRising
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -105,8 +105,8 @@ func (i2c *I2C) Configure(config I2CConfig) error {
|
|||||||
if config.Frequency == 0 {
|
if config.Frequency == 0 {
|
||||||
config.Frequency = defaultBaud
|
config.Frequency = defaultBaud
|
||||||
}
|
}
|
||||||
config.SDA.Configure(PinConfig{PinI2C})
|
config.SDA.Configure(PinConfig{pinI2C})
|
||||||
config.SCL.Configure(PinConfig{PinI2C})
|
config.SCL.Configure(PinConfig{pinI2C})
|
||||||
return i2c.init(config)
|
return i2c.init(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ func (pwm *pwmGroup) Channel(pin Pin) (channel uint8, err error) {
|
|||||||
if pin > maxPWMPins || pwmGPIOToSlice(pin) != pwm.peripheral() {
|
if pin > maxPWMPins || pwmGPIOToSlice(pin) != pwm.peripheral() {
|
||||||
return 3, ErrInvalidOutputPin
|
return 3, ErrInvalidOutputPin
|
||||||
}
|
}
|
||||||
pin.Configure(PinConfig{PinPWM})
|
pin.Configure(PinConfig{pinPWM})
|
||||||
return pwmGPIOToChannel(pin), nil
|
return pwmGPIOToChannel(pin), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,10 @@ import (
|
|||||||
const numberOfCycles = 32
|
const numberOfCycles = 32
|
||||||
|
|
||||||
// GetRNG returns 32 bits of semi-random data based on ring oscillator.
|
// GetRNG returns 32 bits of semi-random data based on ring oscillator.
|
||||||
|
//
|
||||||
|
// Unlike some other implementations of GetRNG, these random numbers are not
|
||||||
|
// cryptographically secure and must not be used for cryptographic operations
|
||||||
|
// (nonces, etc).
|
||||||
func GetRNG() (uint32, error) {
|
func GetRNG() (uint32, error) {
|
||||||
var val uint32
|
var val uint32
|
||||||
for i := 0; i < 4; i++ {
|
for i := 0; i < 4; i++ {
|
||||||
|
|||||||
@@ -38,10 +38,9 @@ type SPIConfig struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrLSBNotSupported = errors.New("SPI LSB unsupported on PL022")
|
ErrLSBNotSupported = errors.New("SPI LSB unsupported on PL022")
|
||||||
ErrTxInvalidSliceSize = errors.New("SPI write and read slices must be same size")
|
ErrSPITimeout = errors.New("SPI timeout")
|
||||||
ErrSPITimeout = errors.New("SPI timeout")
|
ErrSPIBaud = errors.New("SPI baud too low or above 66.5Mhz")
|
||||||
ErrSPIBaud = errors.New("SPI baud too low or above 66.5Mhz")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type SPI struct {
|
type SPI struct {
|
||||||
|
|||||||
@@ -42,8 +42,8 @@ func (uart *UART) Configure(config UARTConfig) error {
|
|||||||
rp.UART0_UARTCR_TXE)
|
rp.UART0_UARTCR_TXE)
|
||||||
|
|
||||||
// set GPIO mux to UART for the pins
|
// set GPIO mux to UART for the pins
|
||||||
config.TX.Configure(PinConfig{Mode: PinUART})
|
config.TX.Configure(PinConfig{Mode: pinUART})
|
||||||
config.RX.Configure(PinConfig{Mode: PinUART})
|
config.RX.Configure(PinConfig{Mode: pinUART})
|
||||||
|
|
||||||
// Enable RX IRQ.
|
// Enable RX IRQ.
|
||||||
uart.Interrupt.SetPriority(0x80)
|
uart.Interrupt.SetPriority(0x80)
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ func InitADC() {
|
|||||||
|
|
||||||
// Configure configures an ADC pin to be able to read analog data.
|
// Configure configures an ADC pin to be able to read analog data.
|
||||||
func (a ADC) Configure(ADCConfig) {
|
func (a ADC) Configure(ADCConfig) {
|
||||||
a.Pin.Configure(PinConfig{Mode: PinInputModeAnalog})
|
a.Pin.Configure(PinConfig{Mode: pinInputModeAnalog})
|
||||||
|
|
||||||
// set sample time
|
// set sample time
|
||||||
ch := a.getChannel()
|
ch := a.getChannel()
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ func InitADC() {
|
|||||||
|
|
||||||
// Configure configures an ADC pin to be able to read analog data.
|
// Configure configures an ADC pin to be able to read analog data.
|
||||||
func (a ADC) Configure(ADCConfig) {
|
func (a ADC) Configure(ADCConfig) {
|
||||||
a.Pin.ConfigureAltFunc(PinConfig{Mode: PinInputAnalog}, 0)
|
a.Pin.ConfigureAltFunc(PinConfig{Mode: pinInputAnalog}, 0)
|
||||||
|
|
||||||
// set sample time
|
// set sample time
|
||||||
ch := a.getChannel()
|
ch := a.getChannel()
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ func (i2c *I2C) Configure(config I2CConfig) error {
|
|||||||
|
|
||||||
// default to 100 kHz (Sm, standard mode) if no frequency is set
|
// default to 100 kHz (Sm, standard mode) if no frequency is set
|
||||||
if config.Frequency == 0 {
|
if config.Frequency == 0 {
|
||||||
config.Frequency = TWI_FREQ_100KHZ
|
config.Frequency = 100 * KHz
|
||||||
}
|
}
|
||||||
|
|
||||||
// configure I2C input clock
|
// configure I2C input clock
|
||||||
|
|||||||
@@ -102,8 +102,8 @@ func (i2c *I2C) Tx(addr uint16, w, r []byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (i2c *I2C) configurePins(config I2CConfig) {
|
func (i2c *I2C) configurePins(config I2CConfig) {
|
||||||
config.SCL.ConfigureAltFunc(PinConfig{Mode: PinModeI2CSCL}, i2c.AltFuncSelector)
|
config.SCL.ConfigureAltFunc(PinConfig{Mode: pinModeI2CSCL}, i2c.AltFuncSelector)
|
||||||
config.SDA.ConfigureAltFunc(PinConfig{Mode: PinModeI2CSDA}, i2c.AltFuncSelector)
|
config.SDA.ConfigureAltFunc(PinConfig{Mode: pinModeI2CSDA}, i2c.AltFuncSelector)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i2c *I2C) controllerTransmit(addr uint16, w []byte) error {
|
func (i2c *I2C) controllerTransmit(addr uint16, w []byte) error {
|
||||||
|
|||||||
@@ -14,29 +14,28 @@ import (
|
|||||||
const (
|
const (
|
||||||
// Mode Flag
|
// Mode Flag
|
||||||
PinOutput PinMode = 0
|
PinOutput PinMode = 0
|
||||||
PinInput PinMode = PinInputFloating
|
PinInput PinMode = 1
|
||||||
PinInputFloating PinMode = 1
|
|
||||||
PinInputPulldown PinMode = 2
|
PinInputPulldown PinMode = 2
|
||||||
PinInputPullup PinMode = 3
|
PinInputPullup PinMode = 3
|
||||||
|
|
||||||
// for UART
|
// for UART
|
||||||
PinModeUARTTX PinMode = 4
|
pinModeUARTTX PinMode = 4
|
||||||
PinModeUARTRX PinMode = 5
|
pinModeUARTRX PinMode = 5
|
||||||
|
|
||||||
// for I2C
|
// for I2C
|
||||||
PinModeI2CSCL PinMode = 6
|
pinModeI2CSCL PinMode = 6
|
||||||
PinModeI2CSDA PinMode = 7
|
pinModeI2CSDA PinMode = 7
|
||||||
|
|
||||||
// for SPI
|
// for SPI
|
||||||
PinModeSPICLK PinMode = 8
|
pinModeSPICLK PinMode = 8
|
||||||
PinModeSPISDO PinMode = 9
|
pinModeSPISDO PinMode = 9
|
||||||
PinModeSPISDI PinMode = 10
|
pinModeSPISDI PinMode = 10
|
||||||
|
|
||||||
// for analog/ADC
|
// for analog/ADC
|
||||||
PinInputAnalog PinMode = 11
|
pinInputAnalog PinMode = 11
|
||||||
|
|
||||||
// for PWM
|
// for PWM
|
||||||
PinModePWMOutput PinMode = 12
|
pinModePWMOutput PinMode = 12
|
||||||
)
|
)
|
||||||
|
|
||||||
// Define several bitfields that have different names across chip families but
|
// Define several bitfields that have different names across chip families but
|
||||||
@@ -83,7 +82,7 @@ func (p Pin) ConfigureAltFunc(config PinConfig, altFunc uint8) {
|
|||||||
switch config.Mode {
|
switch config.Mode {
|
||||||
|
|
||||||
// GPIO
|
// GPIO
|
||||||
case PinInputFloating:
|
case PinInput:
|
||||||
port.MODER.ReplaceBits(gpioModeInput, gpioModeMask, pos)
|
port.MODER.ReplaceBits(gpioModeInput, gpioModeMask, pos)
|
||||||
port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)
|
port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)
|
||||||
case PinInputPulldown:
|
case PinInputPulldown:
|
||||||
@@ -97,24 +96,24 @@ func (p Pin) ConfigureAltFunc(config PinConfig, altFunc uint8) {
|
|||||||
port.OSPEEDR.ReplaceBits(gpioOutputSpeedHigh, gpioOutputSpeedMask, pos)
|
port.OSPEEDR.ReplaceBits(gpioOutputSpeedHigh, gpioOutputSpeedMask, pos)
|
||||||
|
|
||||||
// UART
|
// UART
|
||||||
case PinModeUARTTX:
|
case pinModeUARTTX:
|
||||||
port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
|
port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
|
||||||
port.OSPEEDR.ReplaceBits(gpioOutputSpeedHigh, gpioOutputSpeedMask, pos)
|
port.OSPEEDR.ReplaceBits(gpioOutputSpeedHigh, gpioOutputSpeedMask, pos)
|
||||||
port.PUPDR.ReplaceBits(gpioPullUp, gpioPullMask, pos)
|
port.PUPDR.ReplaceBits(gpioPullUp, gpioPullMask, pos)
|
||||||
p.SetAltFunc(altFunc)
|
p.SetAltFunc(altFunc)
|
||||||
case PinModeUARTRX:
|
case pinModeUARTRX:
|
||||||
port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
|
port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
|
||||||
port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)
|
port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)
|
||||||
p.SetAltFunc(altFunc)
|
p.SetAltFunc(altFunc)
|
||||||
|
|
||||||
// I2C
|
// I2C
|
||||||
case PinModeI2CSCL:
|
case pinModeI2CSCL:
|
||||||
port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
|
port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
|
||||||
port.OTYPER.ReplaceBits(stm32.GPIO_OTYPER_OT0_OpenDrain, stm32.GPIO_OTYPER_OT0_Msk, pos/2)
|
port.OTYPER.ReplaceBits(stm32.GPIO_OTYPER_OT0_OpenDrain, stm32.GPIO_OTYPER_OT0_Msk, pos/2)
|
||||||
port.OSPEEDR.ReplaceBits(gpioOutputSpeedLow, gpioOutputSpeedMask, pos)
|
port.OSPEEDR.ReplaceBits(gpioOutputSpeedLow, gpioOutputSpeedMask, pos)
|
||||||
port.PUPDR.ReplaceBits(gpioPullUp, gpioPullMask, pos)
|
port.PUPDR.ReplaceBits(gpioPullUp, gpioPullMask, pos)
|
||||||
p.SetAltFunc(altFunc)
|
p.SetAltFunc(altFunc)
|
||||||
case PinModeI2CSDA:
|
case pinModeI2CSDA:
|
||||||
port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
|
port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
|
||||||
port.OTYPER.ReplaceBits(stm32.GPIO_OTYPER_OT0_OpenDrain, stm32.GPIO_OTYPER_OT0_Msk, pos/2)
|
port.OTYPER.ReplaceBits(stm32.GPIO_OTYPER_OT0_OpenDrain, stm32.GPIO_OTYPER_OT0_Msk, pos/2)
|
||||||
port.OSPEEDR.ReplaceBits(gpioOutputSpeedLow, gpioOutputSpeedMask, pos)
|
port.OSPEEDR.ReplaceBits(gpioOutputSpeedLow, gpioOutputSpeedMask, pos)
|
||||||
@@ -122,31 +121,31 @@ func (p Pin) ConfigureAltFunc(config PinConfig, altFunc uint8) {
|
|||||||
p.SetAltFunc(altFunc)
|
p.SetAltFunc(altFunc)
|
||||||
|
|
||||||
// SPI
|
// SPI
|
||||||
case PinModeSPICLK:
|
case pinModeSPICLK:
|
||||||
port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
|
port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
|
||||||
port.OSPEEDR.ReplaceBits(gpioOutputSpeedHigh, gpioOutputSpeedMask, pos)
|
port.OSPEEDR.ReplaceBits(gpioOutputSpeedHigh, gpioOutputSpeedMask, pos)
|
||||||
port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)
|
port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)
|
||||||
p.SetAltFunc(altFunc)
|
p.SetAltFunc(altFunc)
|
||||||
case PinModeSPISDO:
|
case pinModeSPISDO:
|
||||||
port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
|
port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
|
||||||
port.OSPEEDR.ReplaceBits(gpioOutputSpeedLow, gpioOutputSpeedMask, pos)
|
port.OSPEEDR.ReplaceBits(gpioOutputSpeedLow, gpioOutputSpeedMask, pos)
|
||||||
port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)
|
port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)
|
||||||
p.SetAltFunc(altFunc)
|
p.SetAltFunc(altFunc)
|
||||||
case PinModeSPISDI:
|
case pinModeSPISDI:
|
||||||
port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
|
port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
|
||||||
port.OSPEEDR.ReplaceBits(gpioOutputSpeedLow, gpioOutputSpeedMask, pos)
|
port.OSPEEDR.ReplaceBits(gpioOutputSpeedLow, gpioOutputSpeedMask, pos)
|
||||||
port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)
|
port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)
|
||||||
p.SetAltFunc(altFunc)
|
p.SetAltFunc(altFunc)
|
||||||
|
|
||||||
// PWM
|
// PWM
|
||||||
case PinModePWMOutput:
|
case pinModePWMOutput:
|
||||||
port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
|
port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
|
||||||
port.OSPEEDR.ReplaceBits(gpioOutputSpeedHigh, gpioOutputSpeedMask, pos)
|
port.OSPEEDR.ReplaceBits(gpioOutputSpeedHigh, gpioOutputSpeedMask, pos)
|
||||||
port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)
|
port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)
|
||||||
p.SetAltFunc(altFunc)
|
p.SetAltFunc(altFunc)
|
||||||
|
|
||||||
// ADC
|
// ADC
|
||||||
case PinInputAnalog:
|
case pinInputAnalog:
|
||||||
port.MODER.ReplaceBits(gpioModeAnalog, gpioModeMask, pos)
|
port.MODER.ReplaceBits(gpioModeAnalog, gpioModeMask, pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -183,7 +183,7 @@ func (t *TIM) Channel(pin Pin) (uint8, error) {
|
|||||||
for _, p := range ch.Pins {
|
for _, p := range ch.Pins {
|
||||||
if p.Pin == pin {
|
if p.Pin == pin {
|
||||||
t.configurePin(uint8(chi), p)
|
t.configurePin(uint8(chi), p)
|
||||||
//p.Pin.ConfigureAltFunc(PinConfig{Mode: PinModePWMOutput}, p.AltFunc)
|
//p.Pin.ConfigureAltFunc(PinConfig{Mode: pinModePWMOutput}, p.AltFunc)
|
||||||
return uint8(chi), nil
|
return uint8(chi), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,5 +7,5 @@ package machine
|
|||||||
// register (most MCUs except STM32F1 series).
|
// register (most MCUs except STM32F1 series).
|
||||||
|
|
||||||
func (t *TIM) configurePin(channel uint8, pf PinFunction) {
|
func (t *TIM) configurePin(channel uint8, pf PinFunction) {
|
||||||
pf.Pin.ConfigureAltFunc(PinConfig{Mode: PinModePWMOutput}, pf.AltFunc)
|
pf.Pin.ConfigureAltFunc(PinConfig{Mode: pinModePWMOutput}, pf.AltFunc)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,20 +29,20 @@ const (
|
|||||||
PinOutput50MHz PinMode = 3 // Output mode, max speed 50MHz
|
PinOutput50MHz PinMode = 3 // Output mode, max speed 50MHz
|
||||||
PinOutput PinMode = PinOutput2MHz
|
PinOutput PinMode = PinOutput2MHz
|
||||||
|
|
||||||
PinInputModeAnalog PinMode = 0 // Input analog mode
|
pinInputModeAnalog PinMode = 0 // Input analog mode
|
||||||
PinInputModeFloating PinMode = 4 // Input floating mode
|
pinInputModeFloating PinMode = 4 // Input floating mode
|
||||||
PinInputModePullUpDown PinMode = 8 // Input pull up/down mode
|
pinInputModePullUpDown PinMode = 8 // Input pull up/down mode
|
||||||
PinInputModeReserved PinMode = 12 // Input mode (reserved)
|
pinInputModeReserved PinMode = 12 // Input mode (reserved)
|
||||||
|
|
||||||
PinOutputModeGPPushPull PinMode = 0 // Output mode general purpose push/pull
|
pinOutputModeGPPushPull PinMode = 0 // Output mode general purpose push/pull
|
||||||
PinOutputModeGPOpenDrain PinMode = 4 // Output mode general purpose open drain
|
pinOutputModeGPOpenDrain PinMode = 4 // Output mode general purpose open drain
|
||||||
PinOutputModeAltPushPull PinMode = 8 // Output mode alt. purpose push/pull
|
pinOutputModeAltPushPull PinMode = 8 // Output mode alt. purpose push/pull
|
||||||
PinOutputModeAltOpenDrain PinMode = 12 // Output mode alt. purpose open drain
|
pinOutputModeAltOpenDrain PinMode = 12 // Output mode alt. purpose open drain
|
||||||
|
|
||||||
// Pull-up vs Pull down is not part of the CNF0 / CNF1 bits, but is
|
// Pull-up vs Pull down is not part of the CNF0 / CNF1 bits, but is
|
||||||
// controlled by PxODR. Encoded using the 'spare' bit 5.
|
// controlled by PxODR. Encoded using the 'spare' bit 5.
|
||||||
PinInputPulldown PinMode = PinInputModePullUpDown
|
PinInputPulldown PinMode = pinInputModePullUpDown
|
||||||
PinInputPullup PinMode = PinInputModePullUpDown | 0x10
|
PinInputPullup PinMode = pinInputModePullUpDown | 0x10
|
||||||
)
|
)
|
||||||
|
|
||||||
// Pin constants for all stm32f103 package sizes
|
// Pin constants for all stm32f103 package sizes
|
||||||
@@ -166,7 +166,7 @@ func (p Pin) Configure(config PinConfig) {
|
|||||||
|
|
||||||
// If configured for input pull-up or pull-down, set ODR
|
// If configured for input pull-up or pull-down, set ODR
|
||||||
// for desired pull-up or pull-down.
|
// for desired pull-up or pull-down.
|
||||||
if (config.Mode & 0xf) == PinInputModePullUpDown {
|
if (config.Mode & 0xf) == pinInputModePullUpDown {
|
||||||
var pullup uint32
|
var pullup uint32
|
||||||
if config.Mode == PinInputPullup {
|
if config.Mode == PinInputPullup {
|
||||||
pullup = 1
|
pullup = 1
|
||||||
@@ -290,8 +290,8 @@ func (uart *UART) configurePins(config UARTConfig) {
|
|||||||
default:
|
default:
|
||||||
// use standard TX/RX pins PA9 and PA10
|
// use standard TX/RX pins PA9 and PA10
|
||||||
}
|
}
|
||||||
config.TX.Configure(PinConfig{Mode: PinOutput50MHz + PinOutputModeAltPushPull})
|
config.TX.Configure(PinConfig{Mode: PinOutput50MHz + pinOutputModeAltPushPull})
|
||||||
config.RX.Configure(PinConfig{Mode: PinInputModeFloating})
|
config.RX.Configure(PinConfig{Mode: pinInputModeFloating})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine the divisor for USARTs to get the given baudrate
|
// Determine the divisor for USARTs to get the given baudrate
|
||||||
@@ -363,9 +363,9 @@ func (spi SPI) getBaudRate(config SPIConfig) uint32 {
|
|||||||
|
|
||||||
// Configure SPI pins for input output and clock
|
// Configure SPI pins for input output and clock
|
||||||
func (spi SPI) configurePins(config SPIConfig) {
|
func (spi SPI) configurePins(config SPIConfig) {
|
||||||
config.SCK.Configure(PinConfig{Mode: PinOutput50MHz + PinOutputModeAltPushPull})
|
config.SCK.Configure(PinConfig{Mode: PinOutput50MHz + pinOutputModeAltPushPull})
|
||||||
config.SDO.Configure(PinConfig{Mode: PinOutput50MHz + PinOutputModeAltPushPull})
|
config.SDO.Configure(PinConfig{Mode: PinOutput50MHz + pinOutputModeAltPushPull})
|
||||||
config.SDI.Configure(PinConfig{Mode: PinInputModeFloating})
|
config.SDI.Configure(PinConfig{Mode: pinInputModeFloating})
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------- I2C related types and code
|
//---------- I2C related types and code
|
||||||
@@ -390,8 +390,8 @@ func (i2c *I2C) configurePins(config I2CConfig) {
|
|||||||
stm32.AFIO.MAPR.SetBits(stm32.AFIO_MAPR_I2C1_REMAP)
|
stm32.AFIO.MAPR.SetBits(stm32.AFIO_MAPR_I2C1_REMAP)
|
||||||
}
|
}
|
||||||
|
|
||||||
config.SDA.Configure(PinConfig{Mode: PinOutput50MHz + PinOutputModeAltOpenDrain})
|
config.SDA.Configure(PinConfig{Mode: PinOutput50MHz + pinOutputModeAltOpenDrain})
|
||||||
config.SCL.Configure(PinConfig{Mode: PinOutput50MHz + PinOutputModeAltOpenDrain})
|
config.SCL.Configure(PinConfig{Mode: PinOutput50MHz + pinOutputModeAltOpenDrain})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i2c *I2C) getFreqRange(config I2CConfig) uint32 {
|
func (i2c *I2C) getFreqRange(config I2CConfig) uint32 {
|
||||||
@@ -717,7 +717,7 @@ func (t *TIM) configurePin(channel uint8, pf PinFunction) {
|
|||||||
stm32.AFIO.MAPR.ReplaceBits(remap<<stm32.AFIO_MAPR2_TIM14_REMAP_Pos, stm32.AFIO_MAPR2_TIM14_REMAP_Msk, 0)
|
stm32.AFIO.MAPR.ReplaceBits(remap<<stm32.AFIO_MAPR2_TIM14_REMAP_Pos, stm32.AFIO_MAPR2_TIM14_REMAP_Msk, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
pf.Pin.Configure(PinConfig{Mode: PinOutput + PinOutputModeAltPushPull})
|
pf.Pin.Configure(PinConfig{Mode: PinOutput + pinOutputModeAltPushPull})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TIM) enableMainOutput() {
|
func (t *TIM) enableMainOutput() {
|
||||||
|
|||||||
@@ -640,8 +640,8 @@ const (
|
|||||||
|
|
||||||
func (uart *UART) configurePins(config UARTConfig) {
|
func (uart *UART) configurePins(config UARTConfig) {
|
||||||
// enable the alternate functions on the TX and RX pins
|
// enable the alternate functions on the TX and RX pins
|
||||||
config.TX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTTX}, uart.TxAltFuncSelector)
|
config.TX.ConfigureAltFunc(PinConfig{Mode: pinModeUARTTX}, uart.TxAltFuncSelector)
|
||||||
config.RX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTRX}, uart.RxAltFuncSelector)
|
config.RX.ConfigureAltFunc(PinConfig{Mode: pinModeUARTRX}, uart.RxAltFuncSelector)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (uart *UART) getBaudRateDivisor(baudRate uint32) uint32 {
|
func (uart *UART) getBaudRateDivisor(baudRate uint32) uint32 {
|
||||||
@@ -674,9 +674,9 @@ func (spi SPI) config8Bits() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (spi SPI) configurePins(config SPIConfig) {
|
func (spi SPI) configurePins(config SPIConfig) {
|
||||||
config.SCK.ConfigureAltFunc(PinConfig{Mode: PinModeSPICLK}, spi.AltFuncSelector)
|
config.SCK.ConfigureAltFunc(PinConfig{Mode: pinModeSPICLK}, spi.AltFuncSelector)
|
||||||
config.SDO.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDO}, spi.AltFuncSelector)
|
config.SDO.ConfigureAltFunc(PinConfig{Mode: pinModeSPISDO}, spi.AltFuncSelector)
|
||||||
config.SDI.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDI}, spi.AltFuncSelector)
|
config.SDI.ConfigureAltFunc(PinConfig{Mode: pinModeSPISDI}, spi.AltFuncSelector)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (spi SPI) getBaudRate(config SPIConfig) uint32 {
|
func (spi SPI) getBaudRate(config SPIConfig) uint32 {
|
||||||
@@ -723,8 +723,8 @@ type I2C struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (i2c *I2C) configurePins(config I2CConfig) {
|
func (i2c *I2C) configurePins(config I2CConfig) {
|
||||||
config.SCL.ConfigureAltFunc(PinConfig{Mode: PinModeI2CSCL}, i2c.AltFuncSelector)
|
config.SCL.ConfigureAltFunc(PinConfig{Mode: pinModeI2CSCL}, i2c.AltFuncSelector)
|
||||||
config.SDA.ConfigureAltFunc(PinConfig{Mode: PinModeI2CSDA}, i2c.AltFuncSelector)
|
config.SDA.ConfigureAltFunc(PinConfig{Mode: pinModeI2CSDA}, i2c.AltFuncSelector)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i2c *I2C) getFreqRange(config I2CConfig) uint32 {
|
func (i2c *I2C) getFreqRange(config I2CConfig) uint32 {
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ const APB2_TIM_FREQ = 216e6 // 216MHz
|
|||||||
// Configure the UART.
|
// Configure the UART.
|
||||||
func (uart *UART) configurePins(config UARTConfig) {
|
func (uart *UART) configurePins(config UARTConfig) {
|
||||||
// enable the alternate functions on the TX and RX pins
|
// enable the alternate functions on the TX and RX pins
|
||||||
config.TX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTTX}, uart.TxAltFuncSelector)
|
config.TX.ConfigureAltFunc(PinConfig{Mode: pinModeUARTTX}, uart.TxAltFuncSelector)
|
||||||
config.RX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTRX}, uart.RxAltFuncSelector)
|
config.RX.ConfigureAltFunc(PinConfig{Mode: pinModeUARTRX}, uart.RxAltFuncSelector)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UART baudrate calc based on the bus and clockspeed
|
// UART baudrate calc based on the bus and clockspeed
|
||||||
|
|||||||
@@ -195,8 +195,8 @@ func (p Pin) registerInterrupt() interrupt.Interrupt {
|
|||||||
// Configure the UART.
|
// Configure the UART.
|
||||||
func (uart *UART) configurePins(config UARTConfig) {
|
func (uart *UART) configurePins(config UARTConfig) {
|
||||||
// enable the alternate functions on the TX and RX pins
|
// enable the alternate functions on the TX and RX pins
|
||||||
config.TX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTTX}, uart.TxAltFuncSelector)
|
config.TX.ConfigureAltFunc(PinConfig{Mode: pinModeUARTTX}, uart.TxAltFuncSelector)
|
||||||
config.RX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTRX}, uart.RxAltFuncSelector)
|
config.RX.ConfigureAltFunc(PinConfig{Mode: pinModeUARTRX}, uart.RxAltFuncSelector)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UART baudrate calc based on the bus and clockspeed
|
// UART baudrate calc based on the bus and clockspeed
|
||||||
@@ -289,9 +289,9 @@ func (spi SPI) getBaudRate(config SPIConfig) uint32 {
|
|||||||
|
|
||||||
// Configure SPI pins for input output and clock
|
// Configure SPI pins for input output and clock
|
||||||
func (spi SPI) configurePins(config SPIConfig) {
|
func (spi SPI) configurePins(config SPIConfig) {
|
||||||
config.SCK.ConfigureAltFunc(PinConfig{Mode: PinModeSPICLK}, spi.AltFuncSelector)
|
config.SCK.ConfigureAltFunc(PinConfig{Mode: pinModeSPICLK}, spi.AltFuncSelector)
|
||||||
config.SDO.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDO}, spi.AltFuncSelector)
|
config.SDO.ConfigureAltFunc(PinConfig{Mode: pinModeSPISDO}, spi.AltFuncSelector)
|
||||||
config.SDI.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDI}, spi.AltFuncSelector)
|
config.SDI.ConfigureAltFunc(PinConfig{Mode: pinModeSPISDI}, spi.AltFuncSelector)
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------- I2C related types and code
|
//---------- I2C related types and code
|
||||||
|
|||||||
@@ -280,8 +280,8 @@ func (p Pin) registerInterrupt() interrupt.Interrupt {
|
|||||||
// Configure the UART.
|
// Configure the UART.
|
||||||
func (uart *UART) configurePins(config UARTConfig) {
|
func (uart *UART) configurePins(config UARTConfig) {
|
||||||
// enable the alternate functions on the TX and RX pins
|
// enable the alternate functions on the TX and RX pins
|
||||||
config.TX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTTX}, uart.TxAltFuncSelector)
|
config.TX.ConfigureAltFunc(PinConfig{Mode: pinModeUARTTX}, uart.TxAltFuncSelector)
|
||||||
config.RX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTRX}, uart.RxAltFuncSelector)
|
config.RX.ConfigureAltFunc(PinConfig{Mode: pinModeUARTRX}, uart.RxAltFuncSelector)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UART baudrate calc based on the bus and clockspeed
|
// UART baudrate calc based on the bus and clockspeed
|
||||||
@@ -357,9 +357,9 @@ func (spi SPI) getBaudRate(config SPIConfig) uint32 {
|
|||||||
|
|
||||||
// Configure SPI pins for input output and clock
|
// Configure SPI pins for input output and clock
|
||||||
func (spi SPI) configurePins(config SPIConfig) {
|
func (spi SPI) configurePins(config SPIConfig) {
|
||||||
config.SCK.ConfigureAltFunc(PinConfig{Mode: PinModeSPICLK}, spi.AltFuncSelector)
|
config.SCK.ConfigureAltFunc(PinConfig{Mode: pinModeSPICLK}, spi.AltFuncSelector)
|
||||||
config.SDO.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDO}, spi.AltFuncSelector)
|
config.SDO.ConfigureAltFunc(PinConfig{Mode: pinModeSPISDO}, spi.AltFuncSelector)
|
||||||
config.SDI.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDI}, spi.AltFuncSelector)
|
config.SDI.ConfigureAltFunc(PinConfig{Mode: pinModeSPISDI}, spi.AltFuncSelector)
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------- Timer related code
|
//---------- Timer related code
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ func (uart *UART) configurePins(config UARTConfig) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// enable the alternate functions on the TX and RX pins
|
// enable the alternate functions on the TX and RX pins
|
||||||
config.TX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTTX}, uart.TxAltFuncSelector)
|
config.TX.ConfigureAltFunc(PinConfig{Mode: pinModeUARTTX}, uart.TxAltFuncSelector)
|
||||||
config.RX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTRX}, uart.RxAltFuncSelector)
|
config.RX.ConfigureAltFunc(PinConfig{Mode: pinModeUARTRX}, uart.RxAltFuncSelector)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UART baudrate calc based on the bus and clockspeed
|
// UART baudrate calc based on the bus and clockspeed
|
||||||
|
|||||||
@@ -239,9 +239,9 @@ func (spi SPI) config8Bits() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (spi SPI) configurePins(config SPIConfig) {
|
func (spi SPI) configurePins(config SPIConfig) {
|
||||||
config.SCK.ConfigureAltFunc(PinConfig{Mode: PinModeSPICLK}, spi.AltFuncSelector)
|
config.SCK.ConfigureAltFunc(PinConfig{Mode: pinModeSPICLK}, spi.AltFuncSelector)
|
||||||
config.SDO.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDO}, spi.AltFuncSelector)
|
config.SDO.ConfigureAltFunc(PinConfig{Mode: pinModeSPISDO}, spi.AltFuncSelector)
|
||||||
config.SDI.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDI}, spi.AltFuncSelector)
|
config.SDI.ConfigureAltFunc(PinConfig{Mode: pinModeSPISDI}, spi.AltFuncSelector)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (spi SPI) getBaudRate(config SPIConfig) uint32 {
|
func (spi SPI) getBaudRate(config SPIConfig) uint32 {
|
||||||
@@ -298,8 +298,8 @@ func (i2c *I2C) getFreqRange() uint32 {
|
|||||||
// Configure the UART.
|
// Configure the UART.
|
||||||
func (uart UART) configurePins(config UARTConfig) {
|
func (uart UART) configurePins(config UARTConfig) {
|
||||||
// enable the alternate functions on the TX and RX pins
|
// enable the alternate functions on the TX and RX pins
|
||||||
config.TX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTTX}, uart.TxAltFuncSelector)
|
config.TX.ConfigureAltFunc(PinConfig{Mode: pinModeUARTTX}, uart.TxAltFuncSelector)
|
||||||
config.RX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTRX}, uart.RxAltFuncSelector)
|
config.RX.ConfigureAltFunc(PinConfig{Mode: pinModeUARTRX}, uart.RxAltFuncSelector)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UART baudrate calc based on the bus and clockspeed
|
// UART baudrate calc based on the bus and clockspeed
|
||||||
|
|||||||
+2
-57
@@ -1,5 +1,5 @@
|
|||||||
//go:build !baremetal || (stm32 && !stm32f7x2 && !stm32l5x2) || fe310 || k210 || (nxp && !mk66f18) || atmega
|
//go:build !baremetal || atmega || esp32 || fe310 || k210 || nrf || (nxp && !mk66f18) || rp2040 || sam || (stm32 && !stm32f7x2 && !stm32l5x2)
|
||||||
// +build !baremetal stm32,!stm32f7x2,!stm32l5x2 fe310 k210 nxp,!mk66f18 atmega
|
// +build !baremetal atmega esp32 fe310 k210 nrf nxp,!mk66f18 rp2040 sam stm32,!stm32f7x2,!stm32l5x2
|
||||||
|
|
||||||
package machine
|
package machine
|
||||||
|
|
||||||
@@ -17,58 +17,3 @@ var (
|
|||||||
ErrTxInvalidSliceSize = errors.New("SPI write and read slices must be same size")
|
ErrTxInvalidSliceSize = errors.New("SPI write and read slices must be same size")
|
||||||
errSPIInvalidMachineConfig = errors.New("SPI port was not configured properly by the machine")
|
errSPIInvalidMachineConfig = errors.New("SPI port was not configured properly by the machine")
|
||||||
)
|
)
|
||||||
|
|
||||||
// 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 {
|
|
||||||
var err error
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case w == nil:
|
|
||||||
// read only, so write zero and read a result.
|
|
||||||
for i := range r {
|
|
||||||
r[i], err = spi.Transfer(0)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case r == nil:
|
|
||||||
// write only
|
|
||||||
for _, b := range w {
|
|
||||||
_, err = spi.Transfer(b)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
// write/read
|
|
||||||
if len(w) != len(r) {
|
|
||||||
return ErrTxInvalidSliceSize
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, b := range w {
|
|
||||||
r[i], err = spi.Transfer(b)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
//go:build !baremetal || atmega || fe310 || k210 || (nxp && !mk66f18) || (stm32 && !stm32f7x2 && !stm32l5x2)
|
||||||
|
// +build !baremetal atmega fe310 k210 nxp,!mk66f18 stm32,!stm32f7x2,!stm32l5x2
|
||||||
|
|
||||||
|
// This file implements the SPI Tx function for targets that don't have a custom
|
||||||
|
// (faster) implementation for it.
|
||||||
|
|
||||||
|
package machine
|
||||||
|
|
||||||
|
// 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 {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case w == nil:
|
||||||
|
// read only, so write zero and read a result.
|
||||||
|
for i := range r {
|
||||||
|
r[i], err = spi.Transfer(0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case r == nil:
|
||||||
|
// write only
|
||||||
|
for _, b := range w {
|
||||||
|
_, err = spi.Transfer(b)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
// write/read
|
||||||
|
if len(w) != len(r) {
|
||||||
|
return ErrTxInvalidSliceSize
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, b := range w {
|
||||||
|
r[i], err = spi.Transfer(b)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
+4
-4
@@ -8,20 +8,20 @@ import "errors"
|
|||||||
var errUARTBufferEmpty = errors.New("UART buffer empty")
|
var errUARTBufferEmpty = errors.New("UART buffer empty")
|
||||||
|
|
||||||
// UARTParity is the parity setting to be used for UART communication.
|
// UARTParity is the parity setting to be used for UART communication.
|
||||||
type UARTParity int
|
type UARTParity uint8
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// ParityNone means to not use any parity checking. This is
|
// ParityNone means to not use any parity checking. This is
|
||||||
// the most common setting.
|
// the most common setting.
|
||||||
ParityNone UARTParity = 0
|
ParityNone UARTParity = iota
|
||||||
|
|
||||||
// ParityEven means to expect that the total number of 1 bits sent
|
// ParityEven means to expect that the total number of 1 bits sent
|
||||||
// should be an even number.
|
// should be an even number.
|
||||||
ParityEven UARTParity = 1
|
ParityEven
|
||||||
|
|
||||||
// ParityOdd means to expect that the total number of 1 bits sent
|
// ParityOdd means to expect that the total number of 1 bits sent
|
||||||
// should be an odd number.
|
// should be an odd number.
|
||||||
ParityOdd UARTParity = 2
|
ParityOdd
|
||||||
)
|
)
|
||||||
|
|
||||||
// To implement the UART interface for a board, you must declare a concrete type as follows:
|
// To implement the UART interface for a board, you must declare a concrete type as follows:
|
||||||
|
|||||||
@@ -20,21 +20,46 @@ var heapStartSymbol [0]byte
|
|||||||
//go:extern __global_base
|
//go:extern __global_base
|
||||||
var globalsStartSymbol [0]byte
|
var globalsStartSymbol [0]byte
|
||||||
|
|
||||||
|
const (
|
||||||
|
// wasmMemoryIndex is always zero until the multi-memory feature is used.
|
||||||
|
//
|
||||||
|
// See https://github.com/WebAssembly/multi-memory
|
||||||
|
wasmMemoryIndex = 0
|
||||||
|
|
||||||
|
// wasmPageSize is the size of a page in WebAssembly's 32-bit memory. This
|
||||||
|
// is also its only unit of change.
|
||||||
|
//
|
||||||
|
// See https://www.w3.org/TR/wasm-core-1/#page-size
|
||||||
|
wasmPageSize = 64 * 1024
|
||||||
|
)
|
||||||
|
|
||||||
|
// wasm_memory_size invokes the "memory.size" instruction, which returns the
|
||||||
|
// current size to the memory at the given index (always wasmMemoryIndex), in
|
||||||
|
// pages.
|
||||||
|
//
|
||||||
//export llvm.wasm.memory.size.i32
|
//export llvm.wasm.memory.size.i32
|
||||||
func wasm_memory_size(index int32) int32
|
func wasm_memory_size(index int32) int32
|
||||||
|
|
||||||
|
// wasm_memory_grow invokes the "memory.grow" instruction, which attempts to
|
||||||
|
// increase the size of the memory at the given index (always wasmMemoryIndex),
|
||||||
|
// by the delta (in pages). This returns the previous size on success of -1 on
|
||||||
|
// failure.
|
||||||
|
//
|
||||||
//export llvm.wasm.memory.grow.i32
|
//export llvm.wasm.memory.grow.i32
|
||||||
func wasm_memory_grow(index int32, delta int32) int32
|
func wasm_memory_grow(index int32, delta int32) int32
|
||||||
|
|
||||||
var (
|
var (
|
||||||
heapStart = uintptr(unsafe.Pointer(&heapStartSymbol))
|
// heapStart is the current memory offset which starts the heap. The heap
|
||||||
heapEnd = uintptr(wasm_memory_size(0) * wasmPageSize)
|
// extends from this offset until heapEnd (exclusive).
|
||||||
|
heapStart = uintptr(unsafe.Pointer(&heapStartSymbol))
|
||||||
|
|
||||||
|
// heapEnd is the current memory length in bytes.
|
||||||
|
heapEnd = uintptr(wasm_memory_size(wasmMemoryIndex) * wasmPageSize)
|
||||||
|
|
||||||
globalsStart = uintptr(unsafe.Pointer(&globalsStartSymbol))
|
globalsStart = uintptr(unsafe.Pointer(&globalsStartSymbol))
|
||||||
globalsEnd = uintptr(unsafe.Pointer(&heapStartSymbol))
|
globalsEnd = uintptr(unsafe.Pointer(&heapStartSymbol))
|
||||||
)
|
)
|
||||||
|
|
||||||
const wasmPageSize = 64 * 1024
|
|
||||||
|
|
||||||
func align(ptr uintptr) uintptr {
|
func align(ptr uintptr) uintptr {
|
||||||
// Align to 16, which is the alignment of max_align_t:
|
// Align to 16, which is the alignment of max_align_t:
|
||||||
// https://godbolt.org/z/dYqTsWrGq
|
// https://godbolt.org/z/dYqTsWrGq
|
||||||
@@ -48,77 +73,67 @@ func getCurrentStackPointer() uintptr
|
|||||||
// otherwise.
|
// otherwise.
|
||||||
func growHeap() bool {
|
func growHeap() bool {
|
||||||
// Grow memory by the available size, which means the heap size is doubled.
|
// Grow memory by the available size, which means the heap size is doubled.
|
||||||
memorySize := wasm_memory_size(0)
|
memorySize := wasm_memory_size(wasmMemoryIndex)
|
||||||
result := wasm_memory_grow(0, memorySize)
|
result := wasm_memory_grow(wasmMemoryIndex, memorySize)
|
||||||
if result == -1 {
|
if result == -1 {
|
||||||
// Grow failed.
|
// Grow failed.
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
setHeapEnd(uintptr(wasm_memory_size(0) * wasmPageSize))
|
setHeapEnd(uintptr(wasm_memory_size(wasmMemoryIndex) * wasmPageSize))
|
||||||
|
|
||||||
// Heap has grown successfully.
|
// Heap has grown successfully.
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// The below functions override the default allocator of wasi-libc. This ensures
|
// The below functions override the default allocator of wasi-libc. This ensures
|
||||||
// code linked from other languages can allocate memory on the same heap as the
|
// code linked from other languages can allocate memory without colliding with
|
||||||
// TinyGo heap.
|
// our GC allocations.
|
||||||
|
|
||||||
// Keep track of all the heap allocations while they're in use.
|
var allocs = make(map[uintptr][]byte)
|
||||||
// This is not the most efficient solution but it costs a lot less in code size
|
|
||||||
// compared to a map.
|
|
||||||
var allocs []unsafe.Pointer
|
|
||||||
|
|
||||||
func trackAlloc(ptr unsafe.Pointer) {
|
|
||||||
// Try to find some empty space in the allocs slice.
|
|
||||||
for i, slot := range allocs {
|
|
||||||
if slot == nil {
|
|
||||||
allocs[i] = slot
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Couldn't find this space. Fall back to appending to the end.
|
|
||||||
allocs = append(allocs, ptr)
|
|
||||||
}
|
|
||||||
|
|
||||||
func removeAlloc(ptr unsafe.Pointer) {
|
|
||||||
// Remove the pointer so it can be garbage collected.
|
|
||||||
for i, slot := range allocs {
|
|
||||||
if ptr == slot {
|
|
||||||
allocs[i] = nil
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//export malloc
|
//export malloc
|
||||||
func libc_malloc(size uintptr) unsafe.Pointer {
|
func libc_malloc(size uintptr) unsafe.Pointer {
|
||||||
ptr := alloc(size, nil)
|
buf := make([]byte, size)
|
||||||
trackAlloc(ptr)
|
ptr := unsafe.Pointer(&buf[0])
|
||||||
|
allocs[uintptr(ptr)] = buf
|
||||||
return ptr
|
return ptr
|
||||||
}
|
}
|
||||||
|
|
||||||
//export free
|
//export free
|
||||||
func libc_free(ptr unsafe.Pointer) {
|
func libc_free(ptr unsafe.Pointer) {
|
||||||
removeAlloc(ptr)
|
if ptr == nil {
|
||||||
free(ptr)
|
return
|
||||||
|
}
|
||||||
|
if _, ok := allocs[uintptr(ptr)]; ok {
|
||||||
|
delete(allocs, uintptr(ptr))
|
||||||
|
} else {
|
||||||
|
panic("free: invalid pointer")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//export calloc
|
//export calloc
|
||||||
func libc_calloc(nmemb, size uintptr) unsafe.Pointer {
|
func libc_calloc(nmemb, size uintptr) unsafe.Pointer {
|
||||||
// Note: we could be even more correct here and check that nmemb * size
|
// No difference between calloc and malloc.
|
||||||
// doesn't overflow. However the current implementation should normally work
|
|
||||||
// fine.
|
|
||||||
return libc_malloc(nmemb * size)
|
return libc_malloc(nmemb * size)
|
||||||
}
|
}
|
||||||
|
|
||||||
//export realloc
|
//export realloc
|
||||||
func libc_realloc(oldPtr unsafe.Pointer, size uintptr) unsafe.Pointer {
|
func libc_realloc(oldPtr unsafe.Pointer, size uintptr) unsafe.Pointer {
|
||||||
newPtr := realloc(oldPtr, size)
|
// It's hard to optimize this to expand the current buffer with our GC, but
|
||||||
if newPtr != oldPtr {
|
// it is theoretically possible. For now, just always allocate fresh.
|
||||||
removeAlloc(oldPtr)
|
buf := make([]byte, size)
|
||||||
trackAlloc(newPtr)
|
|
||||||
|
if oldPtr != nil {
|
||||||
|
if oldBuf, ok := allocs[uintptr(oldPtr)]; ok {
|
||||||
|
copy(buf, oldBuf)
|
||||||
|
delete(allocs, uintptr(oldPtr))
|
||||||
|
} else {
|
||||||
|
panic("realloc: invalid pointer")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return newPtr
|
|
||||||
|
ptr := unsafe.Pointer(&buf[0])
|
||||||
|
allocs[uintptr(ptr)] = buf
|
||||||
|
return ptr
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
//go:build runtime_asserts
|
||||||
|
|
||||||
|
package runtime
|
||||||
|
|
||||||
|
// enable assertions for the garbage collector
|
||||||
|
const gcAsserts = true
|
||||||
|
|
||||||
|
// enable asserts for the scheduler
|
||||||
|
const schedulerAsserts = true
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
//go:build !runtime_asserts
|
||||||
|
|
||||||
|
package runtime
|
||||||
|
|
||||||
|
// disable assertions for the garbage collector
|
||||||
|
const gcAsserts = false
|
||||||
|
|
||||||
|
// disable assertions for the scheduler
|
||||||
|
const schedulerAsserts = false
|
||||||
@@ -25,7 +25,9 @@ package runtime
|
|||||||
// heapStart..metadataStart.
|
// heapStart..metadataStart.
|
||||||
//
|
//
|
||||||
// More information:
|
// More information:
|
||||||
|
// https://aykevl.nl/2020/09/gc-tinygo
|
||||||
// https://github.com/micropython/micropython/wiki/Memory-Manager
|
// https://github.com/micropython/micropython/wiki/Memory-Manager
|
||||||
|
// https://github.com/micropython/micropython/blob/master/py/gc.c
|
||||||
// "The Garbage Collection Handbook" by Richard Jones, Antony Hosking, Eliot
|
// "The Garbage Collection Handbook" by Richard Jones, Antony Hosking, Eliot
|
||||||
// Moss.
|
// Moss.
|
||||||
|
|
||||||
@@ -35,11 +37,7 @@ import (
|
|||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Set gcDebug to true to print debug information.
|
const gcDebug = false
|
||||||
const (
|
|
||||||
gcDebug = false // print debug info
|
|
||||||
gcAsserts = gcDebug // perform sanity checks
|
|
||||||
)
|
|
||||||
|
|
||||||
// Some globals + constants for the entire GC.
|
// Some globals + constants for the entire GC.
|
||||||
|
|
||||||
@@ -288,7 +286,14 @@ func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer {
|
|||||||
// could be found. Run a garbage collection cycle to reclaim
|
// could be found. Run a garbage collection cycle to reclaim
|
||||||
// free memory and try again.
|
// free memory and try again.
|
||||||
heapScanCount = 2
|
heapScanCount = 2
|
||||||
GC()
|
freeBytes := runGC()
|
||||||
|
heapSize := uintptr(metadataStart) - heapStart
|
||||||
|
if freeBytes < heapSize/3 {
|
||||||
|
// Ensure there is at least 33% headroom.
|
||||||
|
// This percentage was arbitrarily chosen, and may need to
|
||||||
|
// be tuned in the future.
|
||||||
|
growHeap()
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Even after garbage collection, no free memory could be found.
|
// Even after garbage collection, no free memory could be found.
|
||||||
// Try to increase heap size.
|
// Try to increase heap size.
|
||||||
@@ -379,6 +384,13 @@ func free(ptr unsafe.Pointer) {
|
|||||||
|
|
||||||
// GC performs a garbage collection cycle.
|
// GC performs a garbage collection cycle.
|
||||||
func GC() {
|
func GC() {
|
||||||
|
runGC()
|
||||||
|
}
|
||||||
|
|
||||||
|
// runGC performs a garbage colleciton cycle. It is the internal implementation
|
||||||
|
// of the runtime.GC() function. The difference is that it returns the number of
|
||||||
|
// free bytes in the heap after the GC is finished.
|
||||||
|
func runGC() (freeBytes uintptr) {
|
||||||
if gcDebug {
|
if gcDebug {
|
||||||
println("running collection cycle...")
|
println("running collection cycle...")
|
||||||
}
|
}
|
||||||
@@ -420,12 +432,14 @@ func GC() {
|
|||||||
|
|
||||||
// Sweep phase: free all non-marked objects and unmark marked objects for
|
// Sweep phase: free all non-marked objects and unmark marked objects for
|
||||||
// the next collection cycle.
|
// the next collection cycle.
|
||||||
sweep()
|
freeBytes = sweep()
|
||||||
|
|
||||||
// Show how much has been sweeped, for debugging.
|
// Show how much has been sweeped, for debugging.
|
||||||
if gcDebug {
|
if gcDebug {
|
||||||
dumpHeap()
|
dumpHeap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// markRoots reads all pointers from start to end (exclusive) and if they look
|
// markRoots reads all pointers from start to end (exclusive) and if they look
|
||||||
@@ -568,7 +582,8 @@ func markRoot(addr, root uintptr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sweep goes through all memory and frees unmarked memory.
|
// Sweep goes through all memory and frees unmarked memory.
|
||||||
func sweep() {
|
// It returns how many bytes are free in the heap after the sweep.
|
||||||
|
func sweep() (freeBytes uintptr) {
|
||||||
freeCurrentObject := false
|
freeCurrentObject := false
|
||||||
for block := gcBlock(0); block < endBlock; block++ {
|
for block := gcBlock(0); block < endBlock; block++ {
|
||||||
switch block.state() {
|
switch block.state() {
|
||||||
@@ -577,11 +592,13 @@ func sweep() {
|
|||||||
block.markFree()
|
block.markFree()
|
||||||
freeCurrentObject = true
|
freeCurrentObject = true
|
||||||
gcFrees++
|
gcFrees++
|
||||||
|
freeBytes += bytesPerBlock
|
||||||
case blockStateTail:
|
case blockStateTail:
|
||||||
if freeCurrentObject {
|
if freeCurrentObject {
|
||||||
// This is a tail object following an unmarked head.
|
// This is a tail object following an unmarked head.
|
||||||
// Free it now.
|
// Free it now.
|
||||||
block.markFree()
|
block.markFree()
|
||||||
|
freeBytes += bytesPerBlock
|
||||||
}
|
}
|
||||||
case blockStateMark:
|
case blockStateMark:
|
||||||
// This is a marked object. The next tail blocks must not be freed,
|
// This is a marked object. The next tail blocks must not be freed,
|
||||||
@@ -589,8 +606,11 @@ func sweep() {
|
|||||||
// collect this object if it is unreferenced then.
|
// collect this object if it is unreferenced then.
|
||||||
block.unmark()
|
block.unmark()
|
||||||
freeCurrentObject = false
|
freeCurrentObject = false
|
||||||
|
case blockStateFree:
|
||||||
|
freeBytes += bytesPerBlock
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// looksLikePointer returns whether this could be a pointer. Currently, it
|
// looksLikePointer returns whether this could be a pointer. Currently, it
|
||||||
|
|||||||
@@ -11,8 +11,6 @@ import (
|
|||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
const gcAsserts = false // perform sanity checks
|
|
||||||
|
|
||||||
// Ever-incrementing pointer: no memory is freed.
|
// Ever-incrementing pointer: no memory is freed.
|
||||||
var heapptr = heapStart
|
var heapptr = heapStart
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user