mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-07-26 14:48:40 +00:00
Compare commits
31 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| df8add7b60 | |||
| 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:
|
||||
- test-linux:
|
||||
llvm: "14"
|
||||
test-llvm14-go119:
|
||||
docker:
|
||||
- image: golang:1.19beta1-buster
|
||||
steps:
|
||||
- test-linux:
|
||||
llvm: "14"
|
||||
fmt-check: false
|
||||
resource_class: large
|
||||
|
||||
workflows:
|
||||
test-all:
|
||||
@@ -132,6 +126,3 @@ workflows:
|
||||
# This tests our lowest supported versions of Go and LLVM, to make sure at
|
||||
# least the smoke tests still pass.
|
||||
- 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
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.18.1'
|
||||
go-version: '1.19'
|
||||
cache: true
|
||||
- name: Cache LLVM source
|
||||
uses: actions/cache@v3
|
||||
@@ -114,7 +114,7 @@ jobs:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.18'
|
||||
go-version: '1.19'
|
||||
cache: true
|
||||
- name: Build TinyGo
|
||||
run: go install
|
||||
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
# statically linked binary.
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: golang:1.18-alpine
|
||||
image: golang:1.19-alpine
|
||||
steps:
|
||||
- name: Install apk dependencies
|
||||
# tar: needed for actions/cache@v3
|
||||
@@ -118,7 +118,7 @@ jobs:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.18.1'
|
||||
go-version: '1.19'
|
||||
cache: true
|
||||
- name: Install wasmtime
|
||||
run: |
|
||||
@@ -171,7 +171,7 @@ jobs:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.18.1'
|
||||
go-version: '1.19'
|
||||
cache: true
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v2
|
||||
@@ -236,6 +236,8 @@ jobs:
|
||||
run: |
|
||||
make ASSERT=1
|
||||
echo "$(pwd)/build" >> $GITHUB_PATH
|
||||
- name: Test machine package
|
||||
run: make check-machine
|
||||
- name: Test stdlib packages
|
||||
run: make tinygo-test
|
||||
- name: Install Xtensa toolchain
|
||||
@@ -271,7 +273,7 @@ jobs:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.18.1'
|
||||
go-version: '1.19'
|
||||
cache: true
|
||||
- name: Cache LLVM source
|
||||
uses: actions/cache@v3
|
||||
@@ -371,7 +373,7 @@ jobs:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.18.1'
|
||||
go-version: '1.19'
|
||||
cache: true
|
||||
- name: Cache LLVM source
|
||||
uses: actions/cache@v3
|
||||
|
||||
@@ -29,7 +29,7 @@ jobs:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.18.1'
|
||||
go-version: '1.19'
|
||||
cache: true
|
||||
- name: Cache LLVM source
|
||||
uses: actions/cache@v3
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
# 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 && \
|
||||
apt-get install -y apt-utils make cmake clang-11 binutils-avr gcc-avr avr-libc ninja-build
|
||||
|
||||
@@ -267,6 +267,18 @@ tinygo:
|
||||
test: wasi-libc
|
||||
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test $(GOTESTFLAGS) -timeout=20m -buildmode exe -tags "byollvm osusergo" ./builder ./cgo ./compileopts ./compiler ./interp ./transform .
|
||||
|
||||
# Check whether the machine package matches the documentation.
|
||||
# TODO: improve `tinygo targets` so it doesn't return these invalid targets.
|
||||
CHECK_MACHINE_EXCULDE = \
|
||||
cortex-m-qemu \
|
||||
particle-3rd-gen \
|
||||
riscv-qemu \
|
||||
riscv64-qemu \
|
||||
rp2040 \
|
||||
$(nil)
|
||||
check-machine:
|
||||
$(GO) run ./tools/machinecheck $(filter-out $(CHECK_MACHINE_EXCULDE),$(shell $(TINYGO) targets))
|
||||
|
||||
# Standard library packages that pass tests on darwin, linux, wasi, and windows, but take over a minute in wasi
|
||||
TEST_PACKAGES_SLOW = \
|
||||
compress/bzip2 \
|
||||
@@ -330,7 +342,6 @@ endif
|
||||
# compress/lzw appears to hang on wasi
|
||||
# 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
|
||||
# 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
|
||||
# strconv requires recover() which is not yet supported on wasi
|
||||
# text/template/parse requires recover(), which is not yet supported on wasi
|
||||
@@ -344,7 +355,6 @@ TEST_PACKAGES_LINUX := \
|
||||
crypto/hmac \
|
||||
debug/dwarf \
|
||||
debug/plan9obj \
|
||||
io/fs \
|
||||
io/ioutil \
|
||||
strconv \
|
||||
testing/fstest \
|
||||
@@ -373,12 +383,15 @@ report-stdlib-tests-pass:
|
||||
# Standard library packages that pass tests quickly on the current platform
|
||||
ifeq ($(shell uname),Darwin)
|
||||
TEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_DARWIN)
|
||||
TEST_IOFS := true
|
||||
endif
|
||||
ifeq ($(shell uname),Linux)
|
||||
TEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_LINUX)
|
||||
TEST_IOFS := true
|
||||
endif
|
||||
ifeq ($(OS),Windows_NT)
|
||||
TEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_WINDOWS)
|
||||
TEST_IOFS := false
|
||||
endif
|
||||
|
||||
# Test known-working standard library packages.
|
||||
@@ -386,6 +399,12 @@ endif
|
||||
.PHONY: tinygo-test
|
||||
tinygo-test:
|
||||
$(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 $(TEST_PACKAGES_HOST)
|
||||
tinygo-bench:
|
||||
@@ -611,7 +630,7 @@ endif
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=challenger-rp2040 examples/blinky1
|
||||
@$(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
|
||||
# test 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(),
|
||||
AutomaticStackSize: config.AutomaticStackSize(),
|
||||
DefaultStackSize: config.Target.DefaultStackSize,
|
||||
DefaultStackSize: config.StackSize(),
|
||||
NeedsStackObjects: config.NeedsStackObjects(),
|
||||
Debug: true,
|
||||
}
|
||||
|
||||
+57
-16
@@ -32,6 +32,7 @@ type cgoPackage struct {
|
||||
errors []error
|
||||
currentDir string // current working directory
|
||||
packageDir string // full path to the package to process
|
||||
importPath string
|
||||
fset *token.FileSet
|
||||
tokenFiles map[string]*token.File
|
||||
definedGlobally map[string]ast.Node
|
||||
@@ -39,12 +40,15 @@ type cgoPackage struct {
|
||||
cflags []string // CFlags from #cgo lines
|
||||
ldflags []string // LDFlags from #cgo lines
|
||||
visitedFiles map[string][]byte
|
||||
cgoHeaders []string
|
||||
}
|
||||
|
||||
// cgoFile holds information only for a single Go file (with one or more
|
||||
// `import "C"` statements).
|
||||
type cgoFile struct {
|
||||
*cgoPackage
|
||||
file *ast.File
|
||||
index int
|
||||
defined map[string]ast.Node
|
||||
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
|
||||
// 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.
|
||||
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{
|
||||
currentDir: dir,
|
||||
importPath: importPath,
|
||||
fset: fset,
|
||||
tokenFiles: map[string]*token.File{},
|
||||
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.
|
||||
cf := p.newCGoFile()
|
||||
cf := p.newCGoFile(nil, -1) // dummy *cgoFile for the walker
|
||||
astutil.Apply(p.generated, func(cursor *astutil.Cursor) bool {
|
||||
return cf.walker(cursor, nil)
|
||||
}, nil)
|
||||
|
||||
// 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 {
|
||||
var cgoHeader string
|
||||
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
|
||||
}
|
||||
|
||||
cgoHeaders[i] = cgoHeader
|
||||
p.cgoHeaders[i] = cgoHeader
|
||||
}
|
||||
|
||||
// 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.
|
||||
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{
|
||||
TokPos: token.NoPos,
|
||||
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.
|
||||
for i, f := range files {
|
||||
cf := p.newCGoFile()
|
||||
cf.readNames(cgoHeaders[i], cflagsForCGo, filepath.Base(fset.File(f.Pos()).Name()), func(names map[string]clangCursor) {
|
||||
cf := p.newCGoFile(f, i)
|
||||
cf.readNames(p.cgoHeaders[i], cflagsForCGo, filepath.Base(fset.File(f.Pos()).Name()), func(names map[string]clangCursor) {
|
||||
for _, name := range builtinAliases {
|
||||
// Names such as C.int should not be obtained from C.
|
||||
// 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.
|
||||
//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{
|
||||
cgoPackage: p,
|
||||
file: file,
|
||||
index: index,
|
||||
defined: make(map[string]ast.Node),
|
||||
names: make(map[string]clangCursor),
|
||||
}
|
||||
@@ -1117,8 +1124,11 @@ func (f *cgoFile) getASTDeclName(name string, found clangCursor, iscall bool) st
|
||||
return alias
|
||||
}
|
||||
node := f.getASTDeclNode(name, found, iscall)
|
||||
if _, ok := node.(*ast.FuncDecl); ok && !iscall {
|
||||
return "C." + name + "$funcaddr"
|
||||
if node, ok := node.(*ast.FuncDecl); ok {
|
||||
if !iscall {
|
||||
return node.Name.Name + "$funcaddr"
|
||||
}
|
||||
return node.Name.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
|
||||
// cgo: inconsistent definitions for C.myint
|
||||
// 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
|
||||
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.
|
||||
f.defined[name] = nil
|
||||
node, elaboratedType := f.createASTNode(name, found)
|
||||
node, extra := f.createASTNode(name, found)
|
||||
f.defined[name] = node
|
||||
f.definedGlobally[name] = node
|
||||
switch node := node.(type) {
|
||||
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)
|
||||
// Also add a declaration like the following:
|
||||
// var C.foo$funcaddr unsafe.Pointer
|
||||
@@ -1162,7 +1200,7 @@ func (f *cgoFile) getASTDeclNode(name string, found clangCursor, iscall bool) as
|
||||
Tok: token.VAR,
|
||||
Specs: []ast.Spec{
|
||||
&ast.ValueSpec{
|
||||
Names: []*ast.Ident{{Name: "C." + name + "$funcaddr"}},
|
||||
Names: []*ast.Ident{{Name: node.Name.Name + "$funcaddr"}},
|
||||
Type: &ast.SelectorExpr{
|
||||
X: &ast.Ident{Name: "unsafe"},
|
||||
Sel: &ast.Ident{Name: "Pointer"},
|
||||
@@ -1171,8 +1209,10 @@ func (f *cgoFile) getASTDeclNode(name string, found clangCursor, iscall bool) as
|
||||
},
|
||||
})
|
||||
case *ast.GenDecl:
|
||||
f.definedGlobally[name] = node
|
||||
f.generated.Decls = append(f.generated.Decls, node)
|
||||
case *ast.TypeSpec:
|
||||
f.definedGlobally[name] = node
|
||||
f.generated.Decls = append(f.generated.Decls, &ast.GenDecl{
|
||||
Tok: token.TYPE,
|
||||
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
|
||||
// methods.
|
||||
if elaboratedType != nil {
|
||||
switch elaboratedType := extra.(type) {
|
||||
case *elaboratedTypeInfo:
|
||||
// Add struct bitfields.
|
||||
for _, bitfield := range elaboratedType.bitfields {
|
||||
f.createBitfieldGetter(bitfield, "C."+name)
|
||||
|
||||
+1
-1
@@ -48,7 +48,7 @@ func TestCGo(t *testing.T) {
|
||||
}
|
||||
|
||||
// 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.
|
||||
var typecheckErrors []error
|
||||
|
||||
+33
-4
@@ -4,7 +4,9 @@ package cgo
|
||||
// modification. It does not touch the AST itself.
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/scanner"
|
||||
@@ -43,6 +45,8 @@ typedef struct {
|
||||
GoCXCursor tinygo_clang_getTranslationUnitCursor(CXTranslationUnit tu);
|
||||
unsigned tinygo_clang_visitChildren(GoCXCursor parent, CXCursorVisitor visitor, CXClientData client_data);
|
||||
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);
|
||||
CXType tinygo_clang_getCursorType(GoCXCursor c);
|
||||
GoCXCursor tinygo_clang_getTypeDeclaration(CXType t);
|
||||
@@ -50,6 +54,7 @@ CXType tinygo_clang_getTypedefDeclUnderlyingType(GoCXCursor c);
|
||||
CXType tinygo_clang_getCursorResultType(GoCXCursor c);
|
||||
int tinygo_clang_Cursor_getNumArguments(GoCXCursor c);
|
||||
GoCXCursor tinygo_clang_Cursor_getArgument(GoCXCursor c, unsigned i);
|
||||
enum CX_StorageClass tinygo_clang_Cursor_getStorageClass(GoCXCursor c);
|
||||
CXSourceLocation tinygo_clang_getCursorLocation(GoCXCursor c);
|
||||
CXSourceRange tinygo_clang_getCursorExtent(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
|
||||
// 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)
|
||||
pos := f.getCursorPosition(c)
|
||||
switch kind {
|
||||
@@ -200,19 +205,43 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, *elaborat
|
||||
Kind: ast.Fun,
|
||||
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)
|
||||
decl := &ast.FuncDecl{
|
||||
Doc: &ast.CommentGroup{
|
||||
List: []*ast.Comment{
|
||||
{
|
||||
Slash: pos - 1,
|
||||
Text: "//export " + name,
|
||||
Text: "//export " + exportName,
|
||||
},
|
||||
},
|
||||
},
|
||||
Name: &ast.Ident{
|
||||
NamePos: pos,
|
||||
Name: "C." + name,
|
||||
Name: "C." + localName,
|
||||
Obj: obj,
|
||||
},
|
||||
Type: &ast.FuncType{
|
||||
@@ -263,7 +292,7 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, *elaborat
|
||||
}
|
||||
}
|
||||
obj.Decl = decl
|
||||
return decl, nil
|
||||
return decl, stringSignature
|
||||
case C.CXCursor_StructDecl, C.CXCursor_UnionDecl:
|
||||
typ := f.makeASTRecordType(c, pos)
|
||||
typeName := "C." + name
|
||||
|
||||
@@ -17,6 +17,14 @@ CXString tinygo_clang_getCursorSpelling(CXCursor 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) {
|
||||
return clang_getCursorKind(c);
|
||||
}
|
||||
@@ -45,6 +53,10 @@ CXCursor tinygo_clang_Cursor_getArgument(CXCursor c, unsigned 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) {
|
||||
return clang_getCursorLocation(c);
|
||||
}
|
||||
|
||||
Vendored
+2
@@ -5,6 +5,7 @@ package main
|
||||
int foo(int a, int b);
|
||||
void variadic0();
|
||||
void variadic2(int x, int y, ...);
|
||||
static void staticfunc(int x);
|
||||
|
||||
// Global variable signatures.
|
||||
extern int someValue;
|
||||
@@ -16,6 +17,7 @@ func accessFunctions() {
|
||||
C.foo(3, 4)
|
||||
C.variadic0()
|
||||
C.variadic2(3, 5)
|
||||
C.staticfunc(3)
|
||||
}
|
||||
|
||||
func accessGlobals() {
|
||||
|
||||
Vendored
+5
@@ -55,5 +55,10 @@ func C.variadic2(x C.int, y C.int)
|
||||
|
||||
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
|
||||
var C.someValue C.int
|
||||
|
||||
@@ -175,6 +175,15 @@ func (c *Config) AutomaticStackSize() bool {
|
||||
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
|
||||
// targets (such as wasm) are not yet supported.
|
||||
// We should try and remove as many exceptions as possible in the future, so
|
||||
|
||||
@@ -28,6 +28,7 @@ type Options struct {
|
||||
GC string
|
||||
PanicStrategy string
|
||||
Scheduler string
|
||||
StackSize uint64 // goroutine stack size (if none could be automatically determined)
|
||||
Serial string
|
||||
Work bool // -work flag to print temporary build directory
|
||||
InterpTimeout time.Duration
|
||||
@@ -49,6 +50,8 @@ type Options struct {
|
||||
LLVMFeatures string
|
||||
Directory string
|
||||
PrintJSON bool
|
||||
Monitor bool
|
||||
BaudRate int
|
||||
}
|
||||
|
||||
// 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(),
|
||||
Scheduler: config.Scheduler(),
|
||||
AutomaticStackSize: config.AutomaticStackSize(),
|
||||
DefaultStackSize: config.Target.DefaultStackSize,
|
||||
DefaultStackSize: config.StackSize(),
|
||||
NeedsStackObjects: config.NeedsStackObjects(),
|
||||
}
|
||||
machine, err := NewTargetMachine(compilerConfig)
|
||||
|
||||
@@ -9,8 +9,10 @@ require (
|
||||
github.com/chromedp/chromedp v0.7.6
|
||||
github.com/gofrs/flock v0.8.1
|
||||
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/mattn/go-colorable v0.1.8
|
||||
github.com/mattn/go-tty v0.0.4
|
||||
go.bug.st/serial v1.3.5
|
||||
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261
|
||||
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/go.mod h1:a/NhLweNvqIYMuxcMOuWY516Cimucms3DglDzQP3hKY=
|
||||
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/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
|
||||
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/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/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/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
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/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/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/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/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
|
||||
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/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=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
go.bug.st/serial v1.3.5 h1:k50SqGZCnHZ2MiBQgzccXWG+kd/XpOs1jUljpDDKzaE=
|
||||
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/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-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-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/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/tools v0.1.11 h1:loJ25fNOEhSXfHrpoGj91eCUThwdNX6u24rO1xnNteY=
|
||||
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/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/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/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())
|
||||
dstObj := mem.getWritable(dst.index())
|
||||
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)
|
||||
copy(dstBuf.buf[dst.offset():dst.offset()+nBytes], srcBuf.buf[src.offset():])
|
||||
dstObj.buffer = dstBuf
|
||||
|
||||
+1
-1
@@ -440,7 +440,7 @@ func (p *Package) parseFiles() ([]*ast.File, error) {
|
||||
var initialCFlags []string
|
||||
initialCFlags = append(initialCFlags, p.program.config.CFlags()...)
|
||||
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.CGoHeaders = headerCode
|
||||
for path, hash := range accessedFiles {
|
||||
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/google/shlex"
|
||||
"github.com/inhies/go-bytesize"
|
||||
"github.com/mattn/go-colorable"
|
||||
"github.com/tinygo-org/tinygo/builder"
|
||||
"github.com/tinygo-org/tinygo/compileopts"
|
||||
@@ -422,7 +423,6 @@ func Flash(pkgName, port string, options *compileopts.Options) error {
|
||||
if err != nil {
|
||||
return &commandError{"failed to flash", result.Binary, err}
|
||||
}
|
||||
return nil
|
||||
case "msd":
|
||||
switch fileExt {
|
||||
case ".uf2":
|
||||
@@ -430,13 +430,11 @@ func Flash(pkgName, port string, options *compileopts.Options) error {
|
||||
if err != nil {
|
||||
return &commandError{"failed to flash", result.Binary, err}
|
||||
}
|
||||
return nil
|
||||
case ".hex":
|
||||
err := flashHexUsingMSD(config.Target.FlashVolume, result.Binary, config.Options)
|
||||
if err != nil {
|
||||
return &commandError{"failed to flash", result.Binary, err}
|
||||
}
|
||||
return nil
|
||||
default:
|
||||
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 {
|
||||
return &commandError{"failed to flash", result.Binary, err}
|
||||
}
|
||||
return nil
|
||||
case "bmp":
|
||||
gdb, err := config.Target.LookupGDB()
|
||||
if err != nil {
|
||||
@@ -476,10 +473,13 @@ func Flash(pkgName, port string, options *compileopts.Options) error {
|
||||
if err != nil {
|
||||
return &commandError{"failed to flash", result.Binary, err}
|
||||
}
|
||||
return nil
|
||||
default:
|
||||
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)})
|
||||
}
|
||||
|
||||
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 {
|
||||
if !p.IsUSB {
|
||||
continue
|
||||
@@ -1020,6 +1021,8 @@ func getDefaultPort(portFlag string, usbInterfaces []string) (port string, err e
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
secondaryPorts = append(secondaryPorts, p.Name)
|
||||
}
|
||||
if len(primaryPorts) == 1 {
|
||||
// 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
|
||||
// Unos).
|
||||
ports = primaryPorts
|
||||
}
|
||||
|
||||
if len(ports) == 0 {
|
||||
// fallback
|
||||
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()
|
||||
}
|
||||
} else {
|
||||
// No preferred ports found. Fall back to other serial ports
|
||||
// available in the system.
|
||||
ports = secondaryPorts
|
||||
}
|
||||
default:
|
||||
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(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
|
||||
} else {
|
||||
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, " gdb: run/flash and immediately enter GDB")
|
||||
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, " list: run go list using the TinyGo root")
|
||||
fmt.Fprintln(os.Stderr, " clean: empty cache directory ("+goenv.Get("GOCACHE")+")")
|
||||
@@ -1318,6 +1316,12 @@ func main() {
|
||||
var tags buildutil.TagsFlag
|
||||
flag.Var(&tags, "tags", "a space-separated list of extra build tags")
|
||||
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)")
|
||||
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")
|
||||
@@ -1332,6 +1336,8 @@ func main() {
|
||||
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")
|
||||
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
|
||||
if command == "help" || command == "list" || command == "info" || command == "build" {
|
||||
@@ -1398,6 +1404,7 @@ func main() {
|
||||
GOARCH: goenv.Get("GOARCH"),
|
||||
GOARM: goenv.Get("GOARM"),
|
||||
Target: *target,
|
||||
StackSize: stackSize,
|
||||
Opt: *opt,
|
||||
GC: *gc,
|
||||
PanicStrategy: *panicStrategy,
|
||||
@@ -1420,6 +1427,8 @@ func main() {
|
||||
OpenOCDCommands: ocdCommands,
|
||||
LLVMFeatures: *llvmFeatures,
|
||||
PrintJSON: flagJSON,
|
||||
Monitor: *monitor,
|
||||
BaudRate: *baudrate,
|
||||
}
|
||||
if *printCommands {
|
||||
options.PrintCommands = printCommand
|
||||
@@ -1610,6 +1619,9 @@ func main() {
|
||||
fmt.Println("FAIL")
|
||||
os.Exit(1)
|
||||
}
|
||||
case "monitor":
|
||||
err := Monitor(*port, options)
|
||||
handleCompilerError(err)
|
||||
case "targets":
|
||||
dir := filepath.Join(goenv.Get("TINYGOROOT"), "targets")
|
||||
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
|
||||
// +build nrf52840 stm32 sam,atsamd51 sam,atsame5x rp2040
|
||||
//go:build nrf || stm32 || (sam && atsamd51) || (sam && atsame5x)
|
||||
// +build nrf stm32 sam,atsamd51 sam,atsame5x
|
||||
|
||||
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
|
||||
|
||||
// used to reset into bootloader
|
||||
const RESET_MAGIC_VALUE = 0x07738135
|
||||
const resetMagicValue = 0x07738135
|
||||
|
||||
// GPIO Pins
|
||||
const (
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
package machine
|
||||
|
||||
// used to reset into bootloader
|
||||
const RESET_MAGIC_VALUE = 0x07738135
|
||||
const resetMagicValue = 0x07738135
|
||||
|
||||
// GPIO Pins
|
||||
const (
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
package machine
|
||||
|
||||
// used to reset into bootloader
|
||||
const RESET_MAGIC_VALUE = 0x07738135
|
||||
const resetMagicValue = 0x07738135
|
||||
|
||||
// GPIO Pins
|
||||
const (
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
package machine
|
||||
|
||||
// used to reset into bootloader
|
||||
const RESET_MAGIC_VALUE = 0x07738135
|
||||
const resetMagicValue = 0x07738135
|
||||
|
||||
// GPIO Pins - Digital Low
|
||||
const (
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
)
|
||||
|
||||
// Definition for compatibility, but not used
|
||||
const RESET_MAGIC_VALUE = 0x00000000
|
||||
const resetMagicValue = 0x00000000
|
||||
|
||||
const (
|
||||
LED = PC18
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
package machine
|
||||
|
||||
// used to reset into bootloader
|
||||
const RESET_MAGIC_VALUE = 0xf01669ef
|
||||
const resetMagicValue = 0xf01669ef
|
||||
|
||||
// GPIO Pins
|
||||
const (
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
package machine
|
||||
|
||||
// used to reset into bootloader
|
||||
const RESET_MAGIC_VALUE = 0xf01669ef
|
||||
const resetMagicValue = 0xf01669ef
|
||||
|
||||
// GPIO Pins
|
||||
const (
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
)
|
||||
|
||||
// used to reset into bootloader
|
||||
const RESET_MAGIC_VALUE = 0xf01669ef
|
||||
const resetMagicValue = 0xf01669ef
|
||||
|
||||
// GPIO Pins
|
||||
const (
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
package machine
|
||||
|
||||
// used to reset into bootloader
|
||||
const RESET_MAGIC_VALUE = 0xf01669ef
|
||||
const resetMagicValue = 0xf01669ef
|
||||
|
||||
// GPIO Pins
|
||||
const (
|
||||
|
||||
@@ -245,7 +245,7 @@ const (
|
||||
|
||||
// Other peripheral constants
|
||||
const (
|
||||
RESET_MAGIC_VALUE = 0xF01669EF // Used to reset into bootloader
|
||||
resetMagicValue = 0xF01669EF // Used to reset into bootloader
|
||||
)
|
||||
|
||||
// USB CDC pins
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
package machine
|
||||
|
||||
// used to reset into bootloader
|
||||
const RESET_MAGIC_VALUE = 0xf01669ef
|
||||
const resetMagicValue = 0xf01669ef
|
||||
|
||||
// GPIO Pins
|
||||
const (
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
package machine
|
||||
|
||||
// used to reset into bootloader
|
||||
const RESET_MAGIC_VALUE = 0xf01669ef
|
||||
const resetMagicValue = 0xf01669ef
|
||||
|
||||
// GPIO Pins
|
||||
const (
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
package machine
|
||||
|
||||
// used to reset into bootloader
|
||||
const RESET_MAGIC_VALUE = 0xF01669EF
|
||||
const resetMagicValue = 0xF01669EF
|
||||
|
||||
// Digital pins
|
||||
const (
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
package machine
|
||||
|
||||
// used to reset into bootloader
|
||||
const RESET_MAGIC_VALUE = 0xf01669ef
|
||||
const resetMagicValue = 0xf01669ef
|
||||
|
||||
// GPIO Pins
|
||||
const (
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
package machine
|
||||
|
||||
// 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
|
||||
// communication with the base controller.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
package machine
|
||||
|
||||
// used to reset into bootloader
|
||||
const RESET_MAGIC_VALUE = 0xf01669ef
|
||||
const resetMagicValue = 0xf01669ef
|
||||
|
||||
// GPIO Pins
|
||||
const (
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
package machine
|
||||
|
||||
// used to reset into bootloader
|
||||
const RESET_MAGIC_VALUE = 0xf01669ef
|
||||
const resetMagicValue = 0xf01669ef
|
||||
|
||||
// GPIO Pins
|
||||
const (
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
package machine
|
||||
|
||||
// used to reset into bootloader
|
||||
const RESET_MAGIC_VALUE = 0xf01669ef
|
||||
const resetMagicValue = 0xf01669ef
|
||||
|
||||
// GPIO Pins
|
||||
const (
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
package machine
|
||||
|
||||
// used to reset into bootloader
|
||||
const RESET_MAGIC_VALUE = 0xf01669ef
|
||||
const resetMagicValue = 0xf01669ef
|
||||
|
||||
// GPIO Pins
|
||||
const (
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
package machine
|
||||
|
||||
// used to reset into bootloader
|
||||
const RESET_MAGIC_VALUE = 0xf01669ef
|
||||
const resetMagicValue = 0xf01669ef
|
||||
|
||||
// GPIO Pins
|
||||
const (
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
package machine
|
||||
|
||||
// used to reset into bootloader
|
||||
const RESET_MAGIC_VALUE = 0xf01669ef
|
||||
const resetMagicValue = 0xf01669ef
|
||||
|
||||
const (
|
||||
ADC0 = A0
|
||||
|
||||
@@ -104,7 +104,7 @@ const (
|
||||
|
||||
var (
|
||||
usb_VID uint16 = 0x2886
|
||||
usb_PID uint16 = 0x0045
|
||||
usb_PID uint16 = 0x8045
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
package machine
|
||||
|
||||
// used to reset into bootloader
|
||||
const RESET_MAGIC_VALUE = 0xf01669ef
|
||||
const resetMagicValue = 0xf01669ef
|
||||
|
||||
// GPIO Pins
|
||||
const (
|
||||
|
||||
@@ -8,6 +8,8 @@ import (
|
||||
)
|
||||
|
||||
// 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 (
|
||||
TWI_FREQ_100KHZ = 100000
|
||||
TWI_FREQ_400KHZ = 400000
|
||||
|
||||
@@ -18,6 +18,13 @@ var (
|
||||
// particular chip but instead runs in WebAssembly for example.
|
||||
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
|
||||
// sets the pin as an output and PinInputPullup sets the pin as an input with a
|
||||
// pull-up.
|
||||
|
||||
@@ -26,7 +26,7 @@ type I2CConfig struct {
|
||||
func (i2c *I2C) Configure(config I2CConfig) error {
|
||||
// Default I2C bus speed is 100 kHz.
|
||||
if config.Frequency == 0 {
|
||||
config.Frequency = TWI_FREQ_100KHZ
|
||||
config.Frequency = 100 * KHz
|
||||
}
|
||||
|
||||
// Activate internal pullups for twi.
|
||||
|
||||
@@ -10,7 +10,6 @@ package machine
|
||||
import (
|
||||
"device/arm"
|
||||
"device/sam"
|
||||
"errors"
|
||||
"runtime/interrupt"
|
||||
"unsafe"
|
||||
)
|
||||
@@ -677,7 +676,7 @@ const i2cTimeout = 1000
|
||||
func (i2c *I2C) Configure(config I2CConfig) error {
|
||||
// Default I2C bus speed is 100 kHz.
|
||||
if config.Frequency == 0 {
|
||||
config.Frequency = TWI_FREQ_100KHZ
|
||||
config.Frequency = 100 * KHz
|
||||
}
|
||||
if config.SDA == 0 && config.SCL == 0 {
|
||||
config.SDA = SDA_PIN
|
||||
@@ -1274,10 +1273,6 @@ func (spi SPI) Transfer(w byte) (byte, error) {
|
||||
return byte(spi.Bus.DATA.Get()), nil
|
||||
}
|
||||
|
||||
var (
|
||||
ErrTxInvalidSliceSize = errors.New("SPI write and read slices must be same size")
|
||||
)
|
||||
|
||||
// Tx handles read/write operation for SPI interface. Since SPI is a syncronous write/read
|
||||
// interface, there must always be the same number of bytes written as bytes read.
|
||||
// The Tx method knows about this, and offers a few different ways of calling it.
|
||||
@@ -1740,7 +1735,7 @@ func EnterBootloader() {
|
||||
|
||||
// Perform magic reset into bootloader, as mentioned in
|
||||
// https://github.com/arduino/ArduinoCore-samd/issues/197
|
||||
*(*uint32)(unsafe.Pointer(uintptr(0x20007FFC))) = RESET_MAGIC_VALUE
|
||||
*(*uint32)(unsafe.Pointer(uintptr(0x20007FFC))) = resetMagicValue
|
||||
|
||||
arm.SystemReset()
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ package machine
|
||||
import (
|
||||
"device/arm"
|
||||
"device/sam"
|
||||
"errors"
|
||||
"runtime/interrupt"
|
||||
"unsafe"
|
||||
)
|
||||
@@ -1151,7 +1150,7 @@ const i2cTimeout = 1000
|
||||
func (i2c *I2C) Configure(config I2CConfig) error {
|
||||
// Default I2C bus speed is 100 kHz.
|
||||
if config.Frequency == 0 {
|
||||
config.Frequency = TWI_FREQ_100KHZ
|
||||
config.Frequency = 100 * KHz
|
||||
}
|
||||
|
||||
// Use default I2C pins if not set.
|
||||
@@ -1527,10 +1526,6 @@ func (spi SPI) Transfer(w byte) (byte, error) {
|
||||
return byte(spi.Bus.DATA.Get()), nil
|
||||
}
|
||||
|
||||
var (
|
||||
ErrTxInvalidSliceSize = errors.New("SPI write and read slices must be same size")
|
||||
)
|
||||
|
||||
// Tx handles read/write operation for SPI interface. Since SPI is a syncronous write/read
|
||||
// interface, there must always be the same number of bytes written as bytes read.
|
||||
// The Tx method knows about this, and offers a few different ways of calling it.
|
||||
@@ -1980,7 +1975,7 @@ func EnterBootloader() {
|
||||
|
||||
// Perform magic reset into bootloader, as mentioned in
|
||||
// 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()
|
||||
}
|
||||
|
||||
@@ -59,12 +59,9 @@ type PinChange uint8
|
||||
|
||||
// Pin change interrupt constants for SetInterrupt.
|
||||
const (
|
||||
PinNoInterrupt PinChange = iota
|
||||
PinRising
|
||||
PinRising PinChange = iota + 1
|
||||
PinFalling
|
||||
PinToggle
|
||||
PinLowLevel
|
||||
PinHighLevel
|
||||
)
|
||||
|
||||
// Configure this pin with the given configuration.
|
||||
@@ -190,7 +187,7 @@ func (p Pin) SetInterrupt(change PinChange, callback func(Pin)) (err error) {
|
||||
return ErrInvalidInputPin
|
||||
}
|
||||
|
||||
if callback == nil || change == PinNoInterrupt {
|
||||
if callback == nil {
|
||||
// Disable this pin interrupt
|
||||
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
|
||||
}
|
||||
|
||||
type UARTStopBits int
|
||||
|
||||
const (
|
||||
UARTStopBits_Default UARTStopBits = iota
|
||||
UARTStopBits_1
|
||||
UARTStopBits_1_5
|
||||
UARTStopBits_2
|
||||
)
|
||||
|
||||
const (
|
||||
defaultDataBits = 8
|
||||
defaultStopBit = 1
|
||||
|
||||
@@ -231,7 +231,7 @@ type I2CConfig struct {
|
||||
func (i2c *I2C) Configure(config I2CConfig) error {
|
||||
var i2cClockFrequency uint32 = 32000000
|
||||
if config.Frequency == 0 {
|
||||
config.Frequency = TWI_FREQ_100KHZ
|
||||
config.Frequency = 100 * KHz
|
||||
}
|
||||
|
||||
if config.SDA == 0 && config.SCL == 0 {
|
||||
|
||||
@@ -23,11 +23,17 @@ type PinChange uint8
|
||||
// Pin modes.
|
||||
const (
|
||||
PinInput PinMode = iota
|
||||
PinInputPullUp
|
||||
PinInputPullDown
|
||||
PinInputPullup
|
||||
PinInputPulldown
|
||||
PinOutput
|
||||
)
|
||||
|
||||
// Deprecated: use PinInputPullup and PinInputPulldown instead.
|
||||
const (
|
||||
PinInputPullUp = PinInputPullup
|
||||
PinInputPullDown = PinInputPulldown
|
||||
)
|
||||
|
||||
// FPIOA internal pull resistors.
|
||||
const (
|
||||
fpioaPullNone fpioaPullMode = iota
|
||||
@@ -89,10 +95,10 @@ func (p Pin) Configure(config PinConfig) {
|
||||
case PinInput:
|
||||
p.setFPIOAIOPull(fpioaPullNone)
|
||||
input = true
|
||||
case PinInputPullUp:
|
||||
case PinInputPullup:
|
||||
p.setFPIOAIOPull(fpioaPullUp)
|
||||
input = true
|
||||
case PinInputPullDown:
|
||||
case PinInputPulldown:
|
||||
p.setFPIOAIOPull(fpioaPullDown)
|
||||
input = true
|
||||
case PinOutput:
|
||||
@@ -517,7 +523,7 @@ type I2CConfig struct {
|
||||
func (i2c *I2C) Configure(config I2CConfig) error {
|
||||
|
||||
if config.Frequency == 0 {
|
||||
config.Frequency = TWI_FREQ_100KHZ
|
||||
config.Frequency = 100 * KHz
|
||||
}
|
||||
|
||||
if config.SDA == 0 && config.SCL == 0 {
|
||||
|
||||
@@ -21,8 +21,8 @@ func CPUFrequency() uint32 {
|
||||
const (
|
||||
// GPIO
|
||||
PinInput PinMode = iota
|
||||
PinInputPullUp
|
||||
PinInputPullDown
|
||||
PinInputPullup
|
||||
PinInputPulldown
|
||||
PinOutput
|
||||
PinOutputOpenDrain
|
||||
PinDisable
|
||||
@@ -45,12 +45,16 @@ const (
|
||||
PinModeI2CSCL
|
||||
)
|
||||
|
||||
// Deprecated: use PinInputPullup and PinInputPulldown instead.
|
||||
const (
|
||||
PinInputPullUp = PinInputPullup
|
||||
PinInputPullDown = PinInputPulldown
|
||||
)
|
||||
|
||||
type PinChange uint8
|
||||
|
||||
const (
|
||||
PinLow PinChange = iota
|
||||
PinHigh
|
||||
PinRising
|
||||
PinRising PinChange = iota + 2
|
||||
PinFalling
|
||||
PinToggle
|
||||
)
|
||||
@@ -259,11 +263,11 @@ func (p Pin) Configure(config PinConfig) {
|
||||
gpio.GDIR.ClearBits(p.getMask())
|
||||
pad.Set(dse(7))
|
||||
|
||||
case PinInputPullUp:
|
||||
case PinInputPullup:
|
||||
gpio.GDIR.ClearBits(p.getMask())
|
||||
pad.Set(dse(7) | pke | pue | pup(3) | hys)
|
||||
|
||||
case PinInputPullDown:
|
||||
case PinInputPulldown:
|
||||
gpio.GDIR.ClearBits(p.getMask())
|
||||
pad.Set(dse(7) | pke | pue | hys)
|
||||
|
||||
@@ -387,7 +391,7 @@ func (p Pin) SetInterrupt(change PinChange, callback func(Pin)) error {
|
||||
mask := p.getMask()
|
||||
if nil != callback {
|
||||
switch change {
|
||||
case PinLow, PinHigh, PinRising, PinFalling:
|
||||
case PinRising, PinFalling:
|
||||
gpio.EDGE_SEL.ClearBits(mask)
|
||||
var reg *volatile.Register32
|
||||
var pos uint8
|
||||
@@ -746,7 +750,7 @@ func (p Pin) getMuxMode(config PinConfig) uint32 {
|
||||
switch config.Mode {
|
||||
|
||||
// GPIO
|
||||
case PinInput, PinInputPullUp, PinInputPullDown,
|
||||
case PinInput, PinInputPullup, PinInputPulldown,
|
||||
PinOutput, PinOutputOpenDrain, PinDisable:
|
||||
mode := uint32(0x5) // GPIO is always alternate function 5
|
||||
if forcePath {
|
||||
|
||||
@@ -10,15 +10,6 @@ import (
|
||||
"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 (
|
||||
errI2CWriteTimeout = errors.New("I2C timeout during write")
|
||||
errI2CReadTimeout = errors.New("I2C timeout during read")
|
||||
@@ -174,7 +165,7 @@ func (i2c *I2C) Configure(config I2CConfig) {
|
||||
|
||||
freq := config.Frequency
|
||||
if 0 == freq {
|
||||
freq = TWI_FREQ_DEFAULT
|
||||
freq = 100 * KHz
|
||||
}
|
||||
|
||||
// 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)
|
||||
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
|
||||
for pre := uint32(1); pre <= 128; pre *= 2 {
|
||||
if bestError == 0 {
|
||||
@@ -314,9 +305,9 @@ func (i2c *I2C) setFrequency(freq uint32) {
|
||||
for clkHi := uint32(1); clkHi < 32; clkHi++ {
|
||||
var absError, rate uint32
|
||||
if clkHi == 1 {
|
||||
rate = (TWI_FREQ_BUS / pre) / (1 + 3 + 2 + 2/pre)
|
||||
rate = (24 * MHz / pre) / (1 + 3 + 2 + 2/pre)
|
||||
} else {
|
||||
rate = (TWI_FREQ_BUS / pre) / (3*clkHi + 2 + 2/pre)
|
||||
rate = (24 * MHz / pre) / (3*clkHi + 2 + 2/pre)
|
||||
}
|
||||
if freq > rate {
|
||||
absError = freq - rate
|
||||
@@ -370,15 +361,15 @@ func (i2c *I2C) setFrequency(freq uint32) {
|
||||
mcfgr2, mcfgr3 uint32
|
||||
)
|
||||
const i2cClockStretchTimeout = 15000 // microseconds
|
||||
if freq >= TWI_FREQ_5MHZ {
|
||||
if freq >= 5*MHz {
|
||||
// I2C UltraFastMode 5 MHz
|
||||
mcfgr2 = 0 // disable glitch filters and timeout for UltraFastMode
|
||||
mcfgr3 = 0 //
|
||||
} else if freq >= TWI_FREQ_1MHZ {
|
||||
} else if freq >= 1*MHz {
|
||||
// I2C FastModePlus 1 MHz
|
||||
mcfgr2 = filtsda(1) | filtscl(1) | busidle(2400) // 100us timeout
|
||||
mcfgr3 = pinlow(i2cClockStretchTimeout*24/256 + 1)
|
||||
} else if freq >= TWI_FREQ_400KHZ {
|
||||
} else if freq >= 400*KHz {
|
||||
// I2C FastMode 400 kHz
|
||||
mcfgr2 = filtsda(2) | filtscl(2) | busidle(3600) // 150us timeout
|
||||
mcfgr3 = pinlow(i2cClockStretchTimeout*24/256 + 1)
|
||||
|
||||
@@ -159,8 +159,8 @@ func (uart *UART) Disable() {
|
||||
uart.Bus.CTRL.ClearBits(nxp.LPUART_CTRL_TE | nxp.LPUART_CTRL_RE)
|
||||
|
||||
// put pins back into GPIO mode
|
||||
uart.rx.Configure(PinConfig{Mode: PinInputPullUp})
|
||||
uart.tx.Configure(PinConfig{Mode: PinInputPullUp})
|
||||
uart.rx.Configure(PinConfig{Mode: PinInputPullup})
|
||||
uart.tx.Configure(PinConfig{Mode: PinInputPullup})
|
||||
}
|
||||
uart.configured = false
|
||||
}
|
||||
|
||||
@@ -5,15 +5,10 @@ package machine
|
||||
|
||||
import (
|
||||
"device/nrf"
|
||||
"errors"
|
||||
"runtime/interrupt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrTxInvalidSliceSize = errors.New("SPI write and read slices must be same size")
|
||||
)
|
||||
|
||||
const deviceName = nrf.Device
|
||||
|
||||
const (
|
||||
@@ -230,7 +225,7 @@ func (i2c *I2C) Configure(config I2CConfig) error {
|
||||
|
||||
// Default I2C bus speed is 100 kHz.
|
||||
if config.Frequency == 0 {
|
||||
config.Frequency = TWI_FREQ_100KHZ
|
||||
config.Frequency = 100 * KHz
|
||||
}
|
||||
// Default I2C pins if not set.
|
||||
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_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)
|
||||
} else {
|
||||
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)
|
||||
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 (
|
||||
DFU_MAGIC_SERIAL_ONLY_RESET = 0x4e
|
||||
DFU_MAGIC_UF2_RESET = 0x57
|
||||
DFU_MAGIC_OTA_RESET = 0xA8
|
||||
dfuMagicSerialOnlyReset = 0x4e
|
||||
dfuMagicUF2Reset = 0x57
|
||||
dfuMagicOTAReset = 0xA8
|
||||
)
|
||||
|
||||
// EnterSerialBootloader resets the chip into the serial bootloader. After
|
||||
// reset, it can be flashed using serial/nrfutil.
|
||||
func EnterSerialBootloader() {
|
||||
arm.DisableInterrupts()
|
||||
nrf.POWER.GPREGRET.Set(DFU_MAGIC_SERIAL_ONLY_RESET)
|
||||
nrf.POWER.GPREGRET.Set(dfuMagicSerialOnlyReset)
|
||||
arm.SystemReset()
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ func EnterSerialBootloader() {
|
||||
// can be flashed via nrfutil or by copying a UF2 file to the mass storage device
|
||||
func EnterUF2Bootloader() {
|
||||
arm.DisableInterrupts()
|
||||
nrf.POWER.GPREGRET.Set(DFU_MAGIC_UF2_RESET)
|
||||
nrf.POWER.GPREGRET.Set(dfuMagicUF2Reset)
|
||||
arm.SystemReset()
|
||||
}
|
||||
|
||||
@@ -34,6 +34,6 @@ func EnterUF2Bootloader() {
|
||||
// flashed via an OTA update
|
||||
func EnterOTABootloader() {
|
||||
arm.DisableInterrupts()
|
||||
nrf.POWER.GPREGRET.Set(DFU_MAGIC_OTA_RESET)
|
||||
nrf.POWER.GPREGRET.Set(dfuMagicOTAReset)
|
||||
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 (
|
||||
PinInput PinMode = iota
|
||||
PinInputPullUp
|
||||
PinInputPullDown
|
||||
PinInputPullup
|
||||
PinInputPulldown
|
||||
PinOutput
|
||||
PinOutputOpenDrain
|
||||
PinDisable
|
||||
)
|
||||
|
||||
// Deprecated: use PinInputPullup and PinInputPulldown instead.
|
||||
const (
|
||||
PinInputPullUp = PinInputPullup
|
||||
PinInputPullDown = PinInputPulldown
|
||||
)
|
||||
|
||||
const (
|
||||
PA00 Pin = iota
|
||||
PA01
|
||||
@@ -223,11 +229,11 @@ func (p Pin) Configure(config PinConfig) {
|
||||
gpio.PDDR.ClearBits(1 << pos)
|
||||
pcr.Set((1 << nxp.PORT_PCR0_MUX_Pos))
|
||||
|
||||
case PinInputPullUp:
|
||||
case PinInputPullup:
|
||||
gpio.PDDR.ClearBits(1 << pos)
|
||||
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)
|
||||
pcr.Set((1 << nxp.PORT_PCR0_MUX_Pos) | nxp.PORT_PCR0_PE)
|
||||
|
||||
|
||||
@@ -203,8 +203,8 @@ func (u *UART) Disable() {
|
||||
u.C2.Set(0)
|
||||
|
||||
// reconfigure pin
|
||||
u.DefaultRX.Configure(PinConfig{Mode: PinInputPullUp})
|
||||
u.DefaultTX.Configure(PinConfig{Mode: PinInputPullUp})
|
||||
u.DefaultRX.Configure(PinConfig{Mode: PinInputPullup})
|
||||
u.DefaultTX.Configure(PinConfig{Mode: PinInputPullup})
|
||||
|
||||
// clear flags
|
||||
u.S1.Get()
|
||||
|
||||
@@ -17,8 +17,8 @@ const (
|
||||
adc0_CH ADCChannel = iota
|
||||
adc1_CH
|
||||
adc2_CH
|
||||
adc3_CH // Note: GPIO29 not broken out on pico board
|
||||
ADC_TEMP_SENSOR // Internal temperature sensor channel
|
||||
adc3_CH // Note: GPIO29 not broken out on pico board
|
||||
adcTempSensor // Internal temperature sensor channel
|
||||
)
|
||||
|
||||
// Used to serialise ADC sampling
|
||||
@@ -75,19 +75,17 @@ func (a ADC) GetADCChannel() (c ADCChannel, err error) {
|
||||
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.
|
||||
func (c ADCChannel) Configure(config ADCConfig) error {
|
||||
if config.Reference != 0 {
|
||||
adcAref = config.Reference
|
||||
}
|
||||
if p, err := c.Pin(); err == nil {
|
||||
p.Configure(PinConfig{Mode: PinAnalog})
|
||||
}
|
||||
if c == ADC_TEMP_SENSOR {
|
||||
// Enable temperature sensor bias source
|
||||
rp.ADC.CS.SetBits(rp.ADC_CS_TS_EN)
|
||||
p, err := c.Pin()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.Configure(PinConfig{Mode: PinAnalog})
|
||||
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.
|
||||
// Only works on the ADC_TEMP_SENSOR channel. aka AINSEL=4. Other channels will return 0
|
||||
func (c ADCChannel) ReadTemperature() (millicelsius uint32) {
|
||||
if c != ADC_TEMP_SENSOR {
|
||||
return
|
||||
func ReadTemperature() (millicelsius int32) {
|
||||
if rp.ADC.CS.Get()&rp.ADC_CS_EN == 0 {
|
||||
InitADC()
|
||||
}
|
||||
|
||||
// Enable temperature sensor bias source
|
||||
rp.ADC.CS.SetBits(rp.ADC_CS_TS_EN)
|
||||
|
||||
// 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.
|
||||
|
||||
@@ -10,11 +10,6 @@ import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
KHz = 1000
|
||||
MHz = 1000000
|
||||
)
|
||||
|
||||
func CPUFrequency() uint32 {
|
||||
return 125 * MHz
|
||||
}
|
||||
|
||||
@@ -226,12 +226,8 @@ type PinChange uint8
|
||||
|
||||
// Pin change interrupt constants for SetInterrupt.
|
||||
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
|
||||
PinFalling
|
||||
PinFalling PinChange = 4 << iota
|
||||
// Edge rising
|
||||
PinRising
|
||||
)
|
||||
|
||||
@@ -13,6 +13,10 @@ import (
|
||||
const numberOfCycles = 32
|
||||
|
||||
// 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) {
|
||||
var val uint32
|
||||
for i := 0; i < 4; i++ {
|
||||
|
||||
@@ -38,10 +38,9 @@ type SPIConfig struct {
|
||||
}
|
||||
|
||||
var (
|
||||
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")
|
||||
ErrSPIBaud = errors.New("SPI baud too low or above 66.5Mhz")
|
||||
ErrLSBNotSupported = errors.New("SPI LSB unsupported on PL022")
|
||||
ErrSPITimeout = errors.New("SPI timeout")
|
||||
ErrSPIBaud = errors.New("SPI baud too low or above 66.5Mhz")
|
||||
)
|
||||
|
||||
type SPI struct {
|
||||
|
||||
@@ -137,7 +137,7 @@ func (i2c *I2C) Configure(config I2CConfig) error {
|
||||
|
||||
// default to 100 kHz (Sm, standard mode) if no frequency is set
|
||||
if config.Frequency == 0 {
|
||||
config.Frequency = TWI_FREQ_100KHZ
|
||||
config.Frequency = 100 * KHz
|
||||
}
|
||||
|
||||
// configure I2C input clock
|
||||
|
||||
+2
-57
@@ -1,5 +1,5 @@
|
||||
//go:build !baremetal || (stm32 && !stm32f7x2 && !stm32l5x2) || fe310 || k210 || (nxp && !mk66f18) || atmega
|
||||
// +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 atmega esp32 fe310 k210 nrf nxp,!mk66f18 rp2040 sam stm32,!stm32f7x2,!stm32l5x2
|
||||
|
||||
package machine
|
||||
|
||||
@@ -17,58 +17,3 @@ var (
|
||||
ErrTxInvalidSliceSize = errors.New("SPI write and read slices must be same size")
|
||||
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")
|
||||
|
||||
// UARTParity is the parity setting to be used for UART communication.
|
||||
type UARTParity int
|
||||
type UARTParity uint8
|
||||
|
||||
const (
|
||||
// ParityNone means to not use any parity checking. This is
|
||||
// the most common setting.
|
||||
ParityNone UARTParity = 0
|
||||
ParityNone UARTParity = iota
|
||||
|
||||
// ParityEven means to expect that the total number of 1 bits sent
|
||||
// should be an even number.
|
||||
ParityEven UARTParity = 1
|
||||
ParityEven
|
||||
|
||||
// ParityOdd means to expect that the total number of 1 bits sent
|
||||
// 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:
|
||||
|
||||
@@ -20,21 +20,46 @@ var heapStartSymbol [0]byte
|
||||
//go:extern __global_base
|
||||
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
|
||||
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
|
||||
func wasm_memory_grow(index int32, delta int32) int32
|
||||
|
||||
var (
|
||||
heapStart = uintptr(unsafe.Pointer(&heapStartSymbol))
|
||||
heapEnd = uintptr(wasm_memory_size(0) * wasmPageSize)
|
||||
// heapStart is the current memory offset which starts the heap. The heap
|
||||
// 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))
|
||||
globalsEnd = uintptr(unsafe.Pointer(&heapStartSymbol))
|
||||
)
|
||||
|
||||
const wasmPageSize = 64 * 1024
|
||||
|
||||
func align(ptr uintptr) uintptr {
|
||||
// Align to 16, which is the alignment of max_align_t:
|
||||
// https://godbolt.org/z/dYqTsWrGq
|
||||
@@ -48,77 +73,67 @@ func getCurrentStackPointer() uintptr
|
||||
// otherwise.
|
||||
func growHeap() bool {
|
||||
// Grow memory by the available size, which means the heap size is doubled.
|
||||
memorySize := wasm_memory_size(0)
|
||||
result := wasm_memory_grow(0, memorySize)
|
||||
memorySize := wasm_memory_size(wasmMemoryIndex)
|
||||
result := wasm_memory_grow(wasmMemoryIndex, memorySize)
|
||||
if result == -1 {
|
||||
// Grow failed.
|
||||
return false
|
||||
}
|
||||
|
||||
setHeapEnd(uintptr(wasm_memory_size(0) * wasmPageSize))
|
||||
setHeapEnd(uintptr(wasm_memory_size(wasmMemoryIndex) * wasmPageSize))
|
||||
|
||||
// Heap has grown successfully.
|
||||
return true
|
||||
}
|
||||
|
||||
// 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
|
||||
// TinyGo heap.
|
||||
// code linked from other languages can allocate memory without colliding with
|
||||
// our GC allocations.
|
||||
|
||||
// Keep track of all the heap allocations while they're in use.
|
||||
// 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
|
||||
}
|
||||
}
|
||||
}
|
||||
var allocs = make(map[uintptr][]byte)
|
||||
|
||||
//export malloc
|
||||
func libc_malloc(size uintptr) unsafe.Pointer {
|
||||
ptr := alloc(size, nil)
|
||||
trackAlloc(ptr)
|
||||
buf := make([]byte, size)
|
||||
ptr := unsafe.Pointer(&buf[0])
|
||||
allocs[uintptr(ptr)] = buf
|
||||
return ptr
|
||||
}
|
||||
|
||||
//export free
|
||||
func libc_free(ptr unsafe.Pointer) {
|
||||
removeAlloc(ptr)
|
||||
free(ptr)
|
||||
if ptr == nil {
|
||||
return
|
||||
}
|
||||
if _, ok := allocs[uintptr(ptr)]; ok {
|
||||
delete(allocs, uintptr(ptr))
|
||||
} else {
|
||||
panic("free: invalid pointer")
|
||||
}
|
||||
}
|
||||
|
||||
//export calloc
|
||||
func libc_calloc(nmemb, size uintptr) unsafe.Pointer {
|
||||
// Note: we could be even more correct here and check that nmemb * size
|
||||
// doesn't overflow. However the current implementation should normally work
|
||||
// fine.
|
||||
// No difference between calloc and malloc.
|
||||
return libc_malloc(nmemb * size)
|
||||
}
|
||||
|
||||
//export realloc
|
||||
func libc_realloc(oldPtr unsafe.Pointer, size uintptr) unsafe.Pointer {
|
||||
newPtr := realloc(oldPtr, size)
|
||||
if newPtr != oldPtr {
|
||||
removeAlloc(oldPtr)
|
||||
trackAlloc(newPtr)
|
||||
// It's hard to optimize this to expand the current buffer with our GC, but
|
||||
// it is theoretically possible. For now, just always allocate fresh.
|
||||
buf := make([]byte, size)
|
||||
|
||||
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.
|
||||
//
|
||||
// More information:
|
||||
// https://aykevl.nl/2020/09/gc-tinygo
|
||||
// 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
|
||||
// Moss.
|
||||
|
||||
@@ -35,11 +37,7 @@ import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Set gcDebug to true to print debug information.
|
||||
const (
|
||||
gcDebug = false // print debug info
|
||||
gcAsserts = gcDebug // perform sanity checks
|
||||
)
|
||||
const gcDebug = false
|
||||
|
||||
// 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
|
||||
// free memory and try again.
|
||||
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 {
|
||||
// Even after garbage collection, no free memory could be found.
|
||||
// Try to increase heap size.
|
||||
@@ -379,6 +384,13 @@ func free(ptr unsafe.Pointer) {
|
||||
|
||||
// GC performs a garbage collection cycle.
|
||||
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 {
|
||||
println("running collection cycle...")
|
||||
}
|
||||
@@ -420,12 +432,14 @@ func GC() {
|
||||
|
||||
// Sweep phase: free all non-marked objects and unmark marked objects for
|
||||
// the next collection cycle.
|
||||
sweep()
|
||||
freeBytes = sweep()
|
||||
|
||||
// Show how much has been sweeped, for debugging.
|
||||
if gcDebug {
|
||||
dumpHeap()
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 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.
|
||||
func sweep() {
|
||||
// It returns how many bytes are free in the heap after the sweep.
|
||||
func sweep() (freeBytes uintptr) {
|
||||
freeCurrentObject := false
|
||||
for block := gcBlock(0); block < endBlock; block++ {
|
||||
switch block.state() {
|
||||
@@ -577,11 +592,13 @@ func sweep() {
|
||||
block.markFree()
|
||||
freeCurrentObject = true
|
||||
gcFrees++
|
||||
freeBytes += bytesPerBlock
|
||||
case blockStateTail:
|
||||
if freeCurrentObject {
|
||||
// This is a tail object following an unmarked head.
|
||||
// Free it now.
|
||||
block.markFree()
|
||||
freeBytes += bytesPerBlock
|
||||
}
|
||||
case blockStateMark:
|
||||
// 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.
|
||||
block.unmark()
|
||||
freeCurrentObject = false
|
||||
case blockStateFree:
|
||||
freeBytes += bytesPerBlock
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// looksLikePointer returns whether this could be a pointer. Currently, it
|
||||
|
||||
@@ -11,8 +11,6 @@ import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const gcAsserts = false // perform sanity checks
|
||||
|
||||
// Ever-incrementing pointer: no memory is freed.
|
||||
var heapptr = heapStart
|
||||
|
||||
|
||||
@@ -11,8 +11,6 @@ import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const gcAsserts = false // perform sanity checks
|
||||
|
||||
var gcTotalAlloc uint64 // for runtime.MemStats
|
||||
var gcMallocs uint64
|
||||
var gcFrees uint64
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"inherits": ["nrf52840", "nrf52840-s140v6-uf2"],
|
||||
"build-tags": ["circuitplay_bluefruit"],
|
||||
"serial-port": ["acm:239a:8045", "acm:239a:45"],
|
||||
"serial-port": ["acm:239a:8045"],
|
||||
"msd-volume-name": "CPLAYBTBOOT"
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"build-tags": ["circuitplay_express"],
|
||||
"flash-1200-bps-reset": "true",
|
||||
"flash-method": "msd",
|
||||
"serial-port": ["acm:239a:8018", "acm:239a:18"],
|
||||
"serial-port": ["acm:239a:8018"],
|
||||
"msd-volume-name": "CPLAYBOOT",
|
||||
"msd-firmware-name": "firmware.uf2"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"inherits": ["nrf52840", "nrf52840-s140v6-uf2"],
|
||||
"build-tags": ["clue_alpha"],
|
||||
"serial-port": ["acm:239a:8072", "acm:239a:0072", "acm:239a:0071", "acm:239a:8071"],
|
||||
"serial-port": ["acm:239a:8072", "acm:239a:8071"],
|
||||
"msd-volume-name": "CLUEBOOT"
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"inherits": ["atsamd21g18a"],
|
||||
"build-tags": ["feather_m0"],
|
||||
"serial": "usb",
|
||||
"serial-port": ["acm:239a:801b", "acm:239a:001b", "acm:239a:800b", "acm:239a:000b", "acm:239a:0015"],
|
||||
"serial-port": ["acm:239a:801b", "acm:239a:800b"],
|
||||
"flash-1200-bps-reset": "true",
|
||||
"flash-method": "msd",
|
||||
"msd-volume-name": "FEATHERBOOT",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"inherits": ["atsame51j19a"],
|
||||
"build-tags": ["feather_m4_can"],
|
||||
"serial": "usb",
|
||||
"serial-port": ["acm:239a:80cd", "acm:239a:00cd"],
|
||||
"serial-port": ["acm:239a:80cd"],
|
||||
"flash-1200-bps-reset": "true",
|
||||
"flash-method": "msd",
|
||||
"msd-volume-name": "FTHRCANBOOT",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"inherits": ["atsamd51j19a"],
|
||||
"build-tags": ["feather_m4"],
|
||||
"serial": "usb",
|
||||
"serial-port": ["acm:239a:8022", "acm:239a:0022"],
|
||||
"serial-port": ["acm:239a:8022"],
|
||||
"flash-1200-bps-reset": "true",
|
||||
"flash-method": "msd",
|
||||
"msd-volume-name": "FEATHERBOOT",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"inherits": ["nrf52840", "nrf52840-s140v6-uf2"],
|
||||
"build-tags": ["feather_nrf52840_sense"],
|
||||
"serial-port": ["acm:239a:8087", "acm:239a:0087", "acm:239a:0088", "acm:239a:8088"],
|
||||
"serial-port": ["acm:239a:8087", "acm:239a:8088"],
|
||||
"msd-volume-name": "FTHRSNSBOOT"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"inherits": ["nrf52840", "nrf52840-s140v6-uf2"],
|
||||
"build-tags": ["feather_nrf52840"],
|
||||
"serial-port": ["acm:239a:8029", "acm:239a:0029", "acm:239a:002a", "acm:239a:802a"],
|
||||
"serial-port": ["acm:239a:8029", "acm:239a:802a"],
|
||||
"msd-volume-name": "FTHR840BOOT"
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"inherits": ["atsamd51p20a"],
|
||||
"build-tags": ["grandcentral_m4"],
|
||||
"serial": "usb",
|
||||
"serial-port": ["acm:239a:8031", "acm:239a:0031", "acm:239a:0032"],
|
||||
"serial-port": ["acm:239a:8031"],
|
||||
"flash-1200-bps-reset": "true",
|
||||
"flash-method": "msd",
|
||||
"msd-volume-name": "GCM4BOOT",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"inherits": ["atsamd21g18a"],
|
||||
"build-tags": ["itsybitsy_m0"],
|
||||
"serial": "usb",
|
||||
"serial-port": ["acm:239a:800f", "acm:239a:000f", "acm:239a:8012"],
|
||||
"serial-port": ["acm:239a:800f", "acm:239a:8012"],
|
||||
"flash-1200-bps-reset": "true",
|
||||
"flash-method": "msd",
|
||||
"msd-volume-name": "ITSYBOOT",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"serial": "usb",
|
||||
"flash-1200-bps-reset": "true",
|
||||
"flash-method": "msd",
|
||||
"serial-port": ["acm:239a:802b", "acm:239a:002b"],
|
||||
"serial-port": ["acm:239a:802b"],
|
||||
"msd-volume-name": "ITSYM4BOOT",
|
||||
"msd-firmware-name": "firmware.uf2"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"inherits": ["nrf52840", "nrf52840-s140v6-uf2"],
|
||||
"build-tags": ["itsybitsy_nrf52840"],
|
||||
"serial-port": ["acm:239A:8052", "acm:239A:0052", "acm:239A:0051", "acm:239A:8051"],
|
||||
"serial-port": ["acm:239A:8052", "acm:239A:8051"],
|
||||
"msd-volume-name": "ITSY840BOOT"
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"inherits": ["atsamd51j19a"],
|
||||
"build-tags": ["matrixportal_m4"],
|
||||
"serial": "usb",
|
||||
"serial-port": ["acm:239a:80c9", "acm:239a:00c9", "acm:239a:80ca"],
|
||||
"serial-port": ["acm:239a:80c9", "acm:239a:80ca"],
|
||||
"flash-1200-bps-reset": "true",
|
||||
"flash-method": "msd",
|
||||
"msd-volume-name": "MATRIXBOOT",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"inherits": ["nrf52840", "nrf52840-s140v6-uf2"],
|
||||
"build-tags": ["mdbt50qrx"],
|
||||
"serial-port": ["acm:239a:810b", "acm:239a:010b", "acm:239a:810c"],
|
||||
"serial-port": ["acm:239a:810b", "acm:239a:810c"],
|
||||
"msd-volume-name": "MDBT50QBOOT"
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"inherits": ["atsamd51j19a"],
|
||||
"build-tags": ["metro_m4_airlift"],
|
||||
"serial": "usb",
|
||||
"serial-port": ["acm:239A:8037", "acm:239A:0037"],
|
||||
"serial-port": ["acm:239A:8037"],
|
||||
"flash-1200-bps-reset": "true",
|
||||
"flash-method": "msd",
|
||||
"msd-volume-name": "METROM4BOOT",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"serial": "usb",
|
||||
"flash-1200-bps-reset": "true",
|
||||
"flash-method": "msd",
|
||||
"serial-port": ["acm:239a:8033", "acm:239a:33"],
|
||||
"serial-port": ["acm:239a:8033"],
|
||||
"msd-volume-name": "PYBADGEBOOT",
|
||||
"msd-firmware-name": "arcade.uf2"
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"inherits": ["atsamd51j19a"],
|
||||
"build-tags": ["pygamer"],
|
||||
"serial": "usb",
|
||||
"serial-port": ["acm:239a:803d", "acm:239a:003d", "acm:239a:803e"],
|
||||
"serial-port": ["acm:239a:803d", "acm:239a:803e"],
|
||||
"flash-1200-bps-reset": "true",
|
||||
"flash-method": "msd",
|
||||
"msd-volume-name": "PYGAMERBOOT",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"serial": "usb",
|
||||
"flash-1200-bps-reset": "true",
|
||||
"flash-method": "msd",
|
||||
"serial-port": ["acm:239a:8035", "acm:239a:35", "acm:239a:8036"],
|
||||
"serial-port": ["acm:239a:8035", "acm:239a:8036"],
|
||||
"msd-volume-name": "PORTALBOOT",
|
||||
"msd-firmware-name": "firmware.uf2"
|
||||
}
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
"inherits": ["atsamd21e18a"],
|
||||
"build-tags": ["qtpy"],
|
||||
"serial": "usb",
|
||||
"serial-port": ["acm:239a:80cb", "acm:239a:00cb", "acm:239a:00cc"],
|
||||
"serial-port": ["acm:239a:80cb"],
|
||||
"flash-1200-bps-reset": "true",
|
||||
"flash-method": "msd",
|
||||
"msd-volume-name": "QTPY_BOOT",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"inherits": ["atsamd21e18a"],
|
||||
"build-tags": ["trinket_m0"],
|
||||
"serial": "usb",
|
||||
"serial-port": ["acm:239a:801e", "acm:239a:001e"],
|
||||
"serial-port": ["acm:239a:801e"],
|
||||
"flash-1200-bps-reset": "true",
|
||||
"flash-method": "msd",
|
||||
"msd-volume-name": "TRINKETBOOT",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"inherits": ["atsamd51p19a"],
|
||||
"build-tags": ["wioterminal"],
|
||||
"serial": "usb",
|
||||
"serial-port": ["acm:2886:002d", "acm:2886:802d"],
|
||||
"serial-port": ["acm:2886:802d"],
|
||||
"flash-1200-bps-reset": "true",
|
||||
"flash-method": "msd",
|
||||
"msd-volume-name": "Arduino",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user