Compare commits

..

1 Commits

Author SHA1 Message Date
Isaac Rodman 4223a60823 Add qtpy-rp2040 to TinyGo v0.25.0 2022-09-02 09:26:23 +09:00
137 changed files with 696 additions and 1546 deletions
+10 -1
View File
@@ -118,7 +118,13 @@ jobs:
steps:
- test-linux:
llvm: "14"
resource_class: large
test-llvm14-go119:
docker:
- image: golang:1.19beta1-buster
steps:
- test-linux:
llvm: "14"
fmt-check: false
workflows:
test-all:
@@ -126,3 +132,6 @@ 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
+17 -12
View File
@@ -16,6 +16,10 @@ jobs:
name: build-macos
runs-on: macos-11
steps:
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: '1.18.1'
- name: Install Dependencies
shell: bash
run: |
@@ -31,13 +35,8 @@ jobs:
uses: actions/checkout@v2
with:
submodules: true
- name: Install Go
uses: actions/setup-go@v3
with:
go-version: '1.19'
cache: true
- name: Cache LLVM source
uses: actions/cache@v3
uses: actions/cache@v2
id: cache-llvm-source
with:
key: llvm-source-14-macos-v1
@@ -51,7 +50,7 @@ jobs:
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
run: make llvm-source
- name: Cache LLVM build
uses: actions/cache@v3
uses: actions/cache@v2
id: cache-llvm-build
with:
key: llvm-build-14-macos-v1
@@ -69,7 +68,7 @@ jobs:
make llvm-build
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
- name: Cache wasi-libc sysroot
uses: actions/cache@v3
uses: actions/cache@v2
id: cache-wasi-libc
with:
key: wasi-libc-sysroot-v4
@@ -105,17 +104,23 @@ jobs:
name: homebrew-install
runs-on: macos-latest
steps:
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: '1.18'
- name: Install LLVM
shell: bash
run: |
HOMEBREW_NO_AUTO_UPDATE=1 brew install llvm@14
- name: Checkout
uses: actions/checkout@v2
- name: Install Go
uses: actions/setup-go@v3
- name: Cache Go
uses: actions/cache@v2
with:
go-version: '1.19'
cache: true
key: go-cache-macos-homebrew-v1-${{ hashFiles('go.mod') }}
path: |
~/Library/Caches/go-build
~/go/pkg/mod
- name: Build TinyGo
run: go install
- name: Check binary
+52 -32
View File
@@ -18,13 +18,14 @@ jobs:
# statically linked binary.
runs-on: ubuntu-latest
container:
image: golang:1.19-alpine
image: alpine:3.16
steps:
- name: Install apk dependencies
# tar: needed for actions/cache@v3
# tar: needed for actions/cache@v2
# git+openssh: needed for checkout (I think?)
# gcompat: needed for go binary
# ruby: needed to install fpm
run: apk add tar git openssh make g++ ruby
run: apk add tar git openssh gcompat make g++ ruby
- name: Work around CVE-2022-24765
# We're not on a multi-user machine, so this is safe.
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
@@ -32,15 +33,19 @@ jobs:
uses: actions/checkout@v2
with:
submodules: true
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: '1.18.1'
- name: Cache Go
uses: actions/cache@v3
uses: actions/cache@v2
with:
key: go-cache-linux-alpine-v1-${{ hashFiles('go.mod') }}
path: |
~/.cache/go-build
~/go/pkg/mod
- name: Cache LLVM source
uses: actions/cache@v3
uses: actions/cache@v2
id: cache-llvm-source
with:
key: llvm-source-14-linux-alpine-v1
@@ -54,7 +59,7 @@ jobs:
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
run: make llvm-source
- name: Cache LLVM build
uses: actions/cache@v3
uses: actions/cache@v2
id: cache-llvm-build
with:
key: llvm-build-14-linux-alpine-v1
@@ -72,7 +77,7 @@ jobs:
# Remove unnecessary object files (to reduce cache size).
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
- name: Cache Binaryen
uses: actions/cache@v3
uses: actions/cache@v2
id: cache-binaryen
with:
key: binaryen-linux-alpine-v1
@@ -83,7 +88,7 @@ jobs:
apk add cmake samurai python3
make binaryen STATIC=1
- name: Cache wasi-libc
uses: actions/cache@v3
uses: actions/cache@v2
id: cache-wasi-libc
with:
key: wasi-libc-sysroot-linux-alpine-v1
@@ -116,10 +121,9 @@ jobs:
- name: Checkout
uses: actions/checkout@v2
- name: Install Go
uses: actions/setup-go@v3
uses: actions/setup-go@v2
with:
go-version: '1.19'
cache: true
go-version: '1.18.1'
- name: Install wasmtime
run: |
curl https://wasmtime.dev/install.sh -sSf | bash
@@ -169,10 +173,9 @@ jobs:
simavr \
ninja-build
- name: Install Go
uses: actions/setup-go@v3
uses: actions/setup-go@v2
with:
go-version: '1.19'
cache: true
go-version: '1.18.1'
- name: Install Node.js
uses: actions/setup-node@v2
with:
@@ -181,8 +184,15 @@ jobs:
run: |
curl https://wasmtime.dev/install.sh -sSf | bash
echo "$HOME/.wasmtime/bin" >> $GITHUB_PATH
- name: Cache Go
uses: actions/cache@v2
with:
key: go-cache-linux-asserts-v1-${{ hashFiles('go.mod') }}
path: |
~/.cache/go-build
~/go/pkg/mod
- name: Cache LLVM source
uses: actions/cache@v3
uses: actions/cache@v2
id: cache-llvm-source
with:
key: llvm-source-14-linux-asserts-v2
@@ -196,7 +206,7 @@ jobs:
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
run: make llvm-source
- name: Cache LLVM build
uses: actions/cache@v3
uses: actions/cache@v2
id: cache-llvm-build
with:
key: llvm-build-14-linux-asserts-v1
@@ -212,7 +222,7 @@ jobs:
# Remove unnecessary object files (to reduce cache size).
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
- name: Cache Binaryen
uses: actions/cache@v3
uses: actions/cache@v2
id: cache-binaryen
with:
key: binaryen-linux-asserts-v1
@@ -221,7 +231,7 @@ jobs:
if: steps.cache-binaryen.outputs.cache-hit != 'true'
run: make binaryen
- name: Cache wasi-libc
uses: actions/cache@v3
uses: actions/cache@v2
id: cache-wasi-libc
with:
key: wasi-libc-sysroot-linux-asserts-v5
@@ -236,8 +246,6 @@ 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,12 +279,18 @@ jobs:
g++-arm-linux-gnueabihf \
libc6-dev-armhf-cross
- name: Install Go
uses: actions/setup-go@v3
uses: actions/setup-go@v2
with:
go-version: '1.19'
cache: true
go-version: '1.18.1'
- name: Cache Go
uses: actions/cache@v2
with:
key: go-cache-linux-arm-v2-${{ hashFiles('go.mod') }}
path: |
~/.cache/go-build
~/go/pkg/mod
- name: Cache LLVM source
uses: actions/cache@v3
uses: actions/cache@v2
id: cache-llvm-source
with:
key: llvm-source-14-linux-v2
@@ -290,7 +304,7 @@ jobs:
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
run: make llvm-source
- name: Cache LLVM build
uses: actions/cache@v3
uses: actions/cache@v2
id: cache-llvm-build
with:
key: llvm-build-14-linux-arm-v1
@@ -308,7 +322,7 @@ jobs:
# Remove unnecessary object files (to reduce cache size).
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
- name: Cache Binaryen
uses: actions/cache@v3
uses: actions/cache@v2
id: cache-binaryen
with:
key: binaryen-linux-arm-v1
@@ -371,12 +385,18 @@ jobs:
libc6-dev-arm64-cross \
ninja-build
- name: Install Go
uses: actions/setup-go@v3
uses: actions/setup-go@v2
with:
go-version: '1.19'
cache: true
go-version: '1.18.1'
- name: Cache Go
uses: actions/cache@v2
with:
key: go-cache-linux-arm64-v2-${{ hashFiles('go.mod') }}
path: |
~/.cache/go-build
~/go/pkg/mod
- name: Cache LLVM source
uses: actions/cache@v3
uses: actions/cache@v2
id: cache-llvm-source
with:
key: llvm-source-14-linux-v1
@@ -390,7 +410,7 @@ jobs:
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
run: make llvm-source
- name: Cache LLVM build
uses: actions/cache@v3
uses: actions/cache@v2
id: cache-llvm-build
with:
key: llvm-build-14-linux-arm64-v1
@@ -406,7 +426,7 @@ jobs:
# Remove unnecessary object files (to reduce cache size).
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
- name: Cache Binaryen
uses: actions/cache@v3
uses: actions/cache@v2
id: cache-binaryen
with:
key: binaryen-linux-arm64-v1
+13 -7
View File
@@ -15,6 +15,10 @@ jobs:
build-windows:
runs-on: windows-2022
steps:
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: '1.18.1'
- uses: brechtm/setup-scoop@v2
with:
scoop_update: 'false'
@@ -26,13 +30,15 @@ jobs:
uses: actions/checkout@v2
with:
submodules: true
- name: Install Go
uses: actions/setup-go@v3
- name: Cache Go
uses: actions/cache@v2
with:
go-version: '1.19'
cache: true
key: go-cache-windows-v1-${{ hashFiles('go.mod') }}
path: |
~/AppData/Local/go-build
~/go/pkg/mod
- name: Cache LLVM source
uses: actions/cache@v3
uses: actions/cache@v2
id: cache-llvm-source
with:
key: llvm-source-14-windows-v2
@@ -46,7 +52,7 @@ jobs:
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
run: make llvm-source
- name: Cache LLVM build
uses: actions/cache@v3
uses: actions/cache@v2
id: cache-llvm-build
with:
key: llvm-build-14-windows-v2
@@ -63,7 +69,7 @@ jobs:
# Remove unnecessary object files (to reduce cache size).
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
- name: Cache wasi-libc sysroot
uses: actions/cache@v3
uses: actions/cache@v2
id: cache-wasi-libc
with:
key: wasi-libc-sysroot-v4
+1 -1
View File
@@ -1,5 +1,5 @@
# tinygo-llvm stage obtains the llvm source for TinyGo
FROM golang:1.19 AS tinygo-llvm
FROM golang:1.18 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
+10 -41
View File
@@ -267,18 +267,6 @@ 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 \
@@ -338,14 +326,11 @@ TEST_PACKAGES_FAST += crypto/elliptic/internal/fiat
endif
# archive/zip requires os.ReadAt, which is not yet supported on windows
# compress/flate appears to hang on wasi
# compress/lzw appears to hang on wasi
# crypto/hmac fails on wasi, it exits with a "slice out of range" panic
# debug/plan9obj requires os.ReadAt, which is not yet supported on windows
# 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
# io/fs requires os.ReadDir, which is not yet supported on windows or wasi
# testing/fstest requires os.ReadDir, which is not yet supported on windows or wasi
# compress/flate fails windows go 1.18, https://github.com/tinygo-org/tinygo/issues/2762
# compress/lzw fails windows go 1.18 wasi, https://github.com/tinygo-org/tinygo/issues/2762
# Additional standard library packages that pass tests on individual platforms
TEST_PACKAGES_LINUX := \
@@ -355,6 +340,7 @@ TEST_PACKAGES_LINUX := \
crypto/hmac \
debug/dwarf \
debug/plan9obj \
io/fs \
io/ioutil \
strconv \
testing/fstest \
@@ -363,12 +349,7 @@ TEST_PACKAGES_LINUX := \
TEST_PACKAGES_DARWIN := $(TEST_PACKAGES_LINUX)
TEST_PACKAGES_WINDOWS := \
compress/flate \
compress/lzw \
crypto/hmac \
strconv \
text/template/parse \
$(nil)
compress/lzw
# Report platforms on which each standard library package is known to pass tests
jointmp := $(shell echo /tmp/join.$$$$)
@@ -383,15 +364,12 @@ 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.
@@ -399,12 +377,6 @@ 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:
@@ -414,9 +386,9 @@ tinygo-bench-fast:
# Same thing, except for wasi rather than the current platform.
tinygo-test-wasi:
$(TINYGO) test -target wasi $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW) ./tests/runtime_wasi
$(TINYGO) test -target wasi $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW)
tinygo-test-wasi-fast:
$(TINYGO) test -target wasi $(TEST_PACKAGES_FAST) ./tests/runtime_wasi
$(TINYGO) test -target wasi $(TEST_PACKAGES_FAST)
tinygo-bench-wasi:
$(TINYGO) test -target wasi -bench . $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW)
tinygo-bench-wasi-fast:
@@ -438,7 +410,6 @@ tinygo-baremetal:
.PHONY: smoketest
smoketest:
$(TINYGO) version
$(TINYGO) targets > /dev/null
# regression test for #2892
cd tests/testing/recurse && ($(TINYGO) test ./... > recurse.log && cat recurse.log && test $$(wc -l < recurse.log) = 2 && rm recurse.log)
# compile-only platform-independent examples
@@ -548,8 +519,6 @@ endif
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=feather-m4 examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=matrixportal-m4 examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=pybadge examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=metro-m4-airlift examples/blinky1
@@ -630,7 +599,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/temp
$(TINYGO) build -size short -o test.hex -target=trinkey-qt2040 examples/adc_rp2040
@$(MD5SUM) test.hex
# test pwm
$(TINYGO) build -size short -o test.hex -target=itsybitsy-m0 examples/pwm
@@ -714,14 +683,14 @@ ifneq ($(XTENSA), 0)
endif
$(TINYGO) build -size short -o test.bin -target=esp32c3 examples/serial
@$(MD5SUM) test.bin
$(TINYGO) build -size short -o test.bin -target=esp32c3-12f examples/serial
@$(MD5SUM) test.bin
$(TINYGO) build -size short -o test.bin -target=m5stamp-c3 examples/serial
@$(MD5SUM) test.bin
$(TINYGO) build -size short -o test.bin -target=xiao-esp32c3 examples/serial
@$(MD5SUM) test.bin
$(TINYGO) build -size short -o test.hex -target=hifive1b examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=hifive1-qemu examples/serial
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=maixbit examples/blinky1
@$(MD5SUM) test.hex
ifneq ($(WASM), 0)
+1 -1
View File
@@ -125,7 +125,7 @@ The following 91 microcontroller boards are currently supported:
* [Seeed LoRa-E5 Development Kit](https://www.seeedstudio.com/LoRa-E5-Dev-Kit-p-4868.html)
* [Seeed Sipeed MAix BiT](https://www.seeedstudio.com/Sipeed-MAix-BiT-for-RISC-V-AI-IoT-p-2872.html)
* [Seeed Wio Terminal](https://www.seeedstudio.com/Wio-Terminal-p-4509.html)
* [SiFIve HiFive1 Rev B](https://www.sifive.com/boards/hifive1-rev-b)
* [SiFIve HiFive1 Rev B](https://www.sifive.com/boards/hifive1)
* [Sparkfun Thing Plus RP2040](https://www.sparkfun.com/products/17745)
* [ST Micro "Nucleo" F103RB](https://www.st.com/en/evaluation-tools/nucleo-f103rb.html)
* [ST Micro "Nucleo" F722ZE](https://www.st.com/en/evaluation-tools/nucleo-f722ze.html)
+1 -1
View File
@@ -178,7 +178,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
Scheduler: config.Scheduler(),
AutomaticStackSize: config.AutomaticStackSize(),
DefaultStackSize: config.StackSize(),
DefaultStackSize: config.Target.DefaultStackSize,
NeedsStackObjects: config.NeedsStackObjects(),
Debug: true,
}
+16 -57
View File
@@ -32,7 +32,6 @@ 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
@@ -40,15 +39,12 @@ 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
}
@@ -162,10 +158,9 @@ 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, importPath string, fset *token.FileSet, cflags []string, clangHeaders string) (*ast.File, []string, []string, []string, map[string][]byte, []error) {
func Process(files []*ast.File, dir 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{},
@@ -215,13 +210,13 @@ func Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cfl
}
}
// Patch some types, for example *C.char in C.CString.
cf := p.newCGoFile(nil, -1) // dummy *cgoFile for the walker
cf := p.newCGoFile()
astutil.Apply(p.generated, func(cursor *astutil.Cursor) bool {
return cf.walker(cursor, nil)
}, nil)
// Find `import "C"` C fragments in the file.
p.cgoHeaders = make([]string, len(files)) // combined CGo header fragment for each file
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++ {
@@ -280,7 +275,7 @@ func Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cfl
cgoHeader += fragment
}
p.cgoHeaders[i] = cgoHeader
cgoHeaders[i] = cgoHeader
}
// Define CFlags that will be used while parsing the package.
@@ -294,7 +289,7 @@ func Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cfl
}
// Retrieve types such as C.int, C.longlong, etc from C.
p.newCGoFile(nil, -1).readNames(builtinAliasTypedefs, cflagsForCGo, "", func(names map[string]clangCursor) {
p.newCGoFile().readNames(builtinAliasTypedefs, cflagsForCGo, "", func(names map[string]clangCursor) {
gen := &ast.GenDecl{
TokPos: token.NoPos,
Tok: token.TYPE,
@@ -308,8 +303,8 @@ func Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cfl
// Process CGo imports for each file.
for i, f := range files {
cf := p.newCGoFile(f, i)
cf.readNames(p.cgoHeaders[i], cflagsForCGo, filepath.Base(fset.File(f.Pos()).Name()), func(names map[string]clangCursor) {
cf := p.newCGoFile()
cf.readNames(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`
@@ -325,14 +320,12 @@ func Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cfl
// Print the newly generated in-memory AST, for debugging.
//ast.Print(fset, p.generated)
return p.generated, p.cgoHeaders, p.cflags, p.ldflags, p.visitedFiles, p.errors
return p.generated, cgoHeaders, p.cflags, p.ldflags, p.visitedFiles, p.errors
}
func (p *cgoPackage) newCGoFile(file *ast.File, index int) *cgoFile {
func (p *cgoPackage) newCGoFile() *cgoFile {
return &cgoFile{
cgoPackage: p,
file: file,
index: index,
defined: make(map[string]ast.Node),
names: make(map[string]clangCursor),
}
@@ -1124,11 +1117,8 @@ func (f *cgoFile) getASTDeclName(name string, found clangCursor, iscall bool) st
return alias
}
node := f.getASTDeclNode(name, found, iscall)
if node, ok := node.(*ast.FuncDecl); ok {
if !iscall {
return node.Name.Name + "$funcaddr"
}
return node.Name.Name
if _, ok := node.(*ast.FuncDecl); ok && !iscall {
return "C." + name + "$funcaddr"
}
return "C." + name
}
@@ -1152,7 +1142,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), name+" defined previously at "+f.fset.Position(getPos(newNode)).String()+" with a different type")
f.addError(getPos(node), "defined previously at "+f.fset.Position(getPos(newNode)).String()+" with a different type")
}
f.defined[name] = node
return node
@@ -1160,39 +1150,11 @@ 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, extra := f.createASTNode(name, found)
node, elaboratedType := 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
@@ -1200,7 +1162,7 @@ extern __typeof(%s) %s __attribute__((alias(%#v)));
Tok: token.VAR,
Specs: []ast.Spec{
&ast.ValueSpec{
Names: []*ast.Ident{{Name: node.Name.Name + "$funcaddr"}},
Names: []*ast.Ident{{Name: "C." + name + "$funcaddr"}},
Type: &ast.SelectorExpr{
X: &ast.Ident{Name: "unsafe"},
Sel: &ast.Ident{Name: "Pointer"},
@@ -1209,10 +1171,8 @@ extern __typeof(%s) %s __attribute__((alias(%#v)));
},
})
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},
@@ -1226,8 +1186,7 @@ extern __typeof(%s) %s __attribute__((alias(%#v)));
// If this is a struct or union it may need bitfields or union accessor
// methods.
switch elaboratedType := extra.(type) {
case *elaboratedTypeInfo:
if elaboratedType != nil {
// Add struct bitfields.
for _, bitfield := range elaboratedType.bitfields {
f.createBitfieldGetter(bitfield, "C."+name)
+1 -1
View File
@@ -48,7 +48,7 @@ func TestCGo(t *testing.T) {
}
// Process the AST with CGo.
cgoAST, _, _, _, _, cgoErrors := Process([]*ast.File{f}, "testdata", "main", fset, cflags, "")
cgoAST, _, _, _, _, cgoErrors := Process([]*ast.File{f}, "testdata", fset, cflags, "")
// Check the AST for type errors.
var typecheckErrors []error
+4 -33
View File
@@ -4,9 +4,7 @@ package cgo
// modification. It does not touch the AST itself.
import (
"crypto/sha256"
"crypto/sha512"
"encoding/hex"
"fmt"
"go/ast"
"go/scanner"
@@ -45,8 +43,6 @@ 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);
@@ -54,7 +50,6 @@ 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);
@@ -194,7 +189,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, any) {
func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, *elaboratedTypeInfo) {
kind := C.tinygo_clang_getCursorKind(c)
pos := f.getCursorPosition(c)
switch kind {
@@ -205,43 +200,19 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) {
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 " + exportName,
Text: "//export " + name,
},
},
},
Name: &ast.Ident{
NamePos: pos,
Name: "C." + localName,
Name: "C." + name,
Obj: obj,
},
Type: &ast.FuncType{
@@ -292,7 +263,7 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) {
}
}
obj.Decl = decl
return decl, stringSignature
return decl, nil
case C.CXCursor_StructDecl, C.CXCursor_UnionDecl:
typ := f.makeASTRecordType(c, pos)
typeName := "C." + name
-12
View File
@@ -17,14 +17,6 @@ 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);
}
@@ -53,10 +45,6 @@ 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);
}
-2
View File
@@ -5,7 +5,6 @@ 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;
@@ -17,7 +16,6 @@ func accessFunctions() {
C.foo(3, 4)
C.variadic0()
C.variadic2(3, 5)
C.staticfunc(3)
}
func accessGlobals() {
-5
View File
@@ -55,10 +55,5 @@ 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
+1 -17
View File
@@ -175,15 +175,6 @@ 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
@@ -466,14 +457,7 @@ func (c *Config) OpenOCDConfiguration() (args []string, err error) {
args = append(args, "-c", cmd)
}
if c.Target.OpenOCDTransport != "" {
transport := c.Target.OpenOCDTransport
if transport == "swd" {
switch openocdInterface {
case "stlink-dap":
transport = "dapdirect_swd"
}
}
args = append(args, "-c", "transport select "+transport)
args = append(args, "-c", "transport select "+c.Target.OpenOCDTransport)
}
args = append(args, "-f", "target/"+c.Target.OpenOCDTarget+".cfg")
return args, nil
-3
View File
@@ -28,7 +28,6 @@ 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
@@ -50,8 +49,6 @@ 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.
+6 -13
View File
@@ -65,7 +65,7 @@ type TargetSpec struct {
}
// overrideProperties overrides all properties that are set in child into itself using reflection.
func (spec *TargetSpec) overrideProperties(child *TargetSpec) error {
func (spec *TargetSpec) overrideProperties(child *TargetSpec) {
specType := reflect.TypeOf(spec).Elem()
specValue := reflect.ValueOf(spec).Elem()
childValue := reflect.ValueOf(child).Elem()
@@ -95,15 +95,14 @@ func (spec *TargetSpec) overrideProperties(child *TargetSpec) error {
for j := i + 1; j < dst.Len(); j++ {
w := dst.Index(j).String()
if v == w {
return fmt.Errorf("duplicate value '%s' in field %s", v, field.Name)
panic("duplicate value '" + v + "' in field : " + field.Name)
}
}
}
default:
return fmt.Errorf("unknown field type: %s", kind)
panic("unknown field type : " + kind.String())
}
}
return nil
}
// load reads a target specification from the JSON in the given io.Reader. It
@@ -151,17 +150,11 @@ func (spec *TargetSpec) resolveInherits() error {
if err != nil {
return err
}
err = newSpec.overrideProperties(subtarget)
if err != nil {
return err
}
newSpec.overrideProperties(subtarget)
}
// When all properties are loaded, make sure they are properly inherited.
err := newSpec.overrideProperties(spec)
if err != nil {
return err
}
newSpec.overrideProperties(spec)
*spec = *newSpec
return nil
@@ -228,7 +221,7 @@ func LoadTarget(options *Options) (*TargetSpec, error) {
// it includes all parents as specified in the "inherits" key.
err = spec.resolveInherits()
if err != nil {
return nil, fmt.Errorf("%s : %w", options.Target, err)
return nil, err
}
if spec.Scheduler == "asyncify" {
+1 -1
View File
@@ -79,7 +79,7 @@ func TestCompiler(t *testing.T) {
RelocationModel: config.RelocationModel(),
Scheduler: config.Scheduler(),
AutomaticStackSize: config.AutomaticStackSize(),
DefaultStackSize: config.StackSize(),
DefaultStackSize: config.Target.DefaultStackSize,
NeedsStackObjects: config.NeedsStackObjects(),
}
machine, err := NewTargetMachine(compilerConfig)
+10 -12
View File
@@ -163,20 +163,18 @@ func (c *compilerContext) getFunction(fn *ssa.Function) llvm.Value {
// External/exported functions may not retain pointer values.
// https://golang.org/cmd/cgo/#hdr-Passing_pointers
if info.exported {
if c.archFamily() == "wasm32" {
// We need to add the wasm-import-module and the wasm-import-name
// attributes.
module := info.module
if module == "" {
module = "env"
}
llvmFn.AddFunctionAttr(c.ctx.CreateStringAttribute("wasm-import-module", module))
// Set the wasm-import-module attribute if the function's module is set.
if info.module != "" {
name := info.importName
if name == "" {
name = info.linkName
// We need to add the wasm-import-module and the wasm-import-name
wasmImportModuleAttr := c.ctx.CreateStringAttribute("wasm-import-module", info.module)
llvmFn.AddFunctionAttr(wasmImportModuleAttr)
// Add the Wasm Import Name, if we are a named wasm import
if info.importName != "" {
wasmImportNameAttr := c.ctx.CreateStringAttribute("wasm-import-name", info.importName)
llvmFn.AddFunctionAttr(wasmImportNameAttr)
}
llvmFn.AddFunctionAttr(c.ctx.CreateStringAttribute("wasm-import-name", name))
}
nocaptureKind := llvm.AttributeKindID("nocapture")
nocapture := c.ctx.CreateEnumAttribute(nocaptureKind, 0)
+2 -2
View File
@@ -62,7 +62,7 @@ declare void @main.undefinedFunctionNotInSection(i8*) #0
attributes #0 = { "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
attributes #1 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
attributes #2 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" "wasm-export-name"="extern_func" "wasm-import-module"="env" "wasm-import-name"="extern_func" }
attributes #2 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" "wasm-export-name"="extern_func" }
attributes #3 = { inlinehint nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
attributes #4 = { noinline nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
attributes #5 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" "wasm-export-name"="exportedFunctionInSection" "wasm-import-module"="env" "wasm-import-name"="exportedFunctionInSection" }
attributes #5 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" "wasm-export-name"="exportedFunctionInSection" }
-2
View File
@@ -9,10 +9,8 @@ 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
+11 -13
View File
@@ -12,6 +12,7 @@ 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=
@@ -22,47 +23,44 @@ 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/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
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=
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=
-5
View File
@@ -369,11 +369,6 @@ 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
View File
@@ -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.ImportPath, p.program.fset, initialCFlags, p.program.clangHeaders)
generated, headerCode, cflags, ldflags, accessedFiles, errs := cgo.Process(files, p.program.workingDir, p.program.fset, initialCFlags, p.program.clangHeaders)
p.CFlags = append(initialCFlags, cflags...)
p.CGoHeaders = headerCode
for path, hash := range accessedFiles {
+23 -55
View File
@@ -26,7 +26,6 @@ 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"
@@ -244,36 +243,17 @@ func Test(pkgName string, stdout, stderr io.Writer, options *compileopts.Options
// Tests are always run in the package directory.
cmd.Dir = result.MainDir
// wasmtime is the default emulator used for `-target=wasi`. wasmtime
// is a WebAssembly runtime CLI with WASI enabled by default. However,
// only stdio are allowed by default. For example, while STDOUT routes
// to the host, other files don't. It also does not inherit environment
// variables from the host. Some tests read testdata files, often from
// outside the package directory. Other tests require temporary
// writeable directories. We allow this by adding wasmtime flags below.
// Wasmtime needs a few extra flags to work.
if config.EmulatorName() == "wasmtime" {
// At this point, The current working directory is at the package
// directory. Ex. $GOROOT/src/compress/flate for compress/flate.
// buildAndRun has already added arguments for wasmtime, that allow
// read-access to files such as "testdata/huffman-zero.in".
//
// Ex. main(.wasm) --dir=. -- -test.v
// Below adds additional wasmtime flags in case a test reads files
// outside its directory, like "../testdata/e.txt". This allows any
// relative directory up to the module root, even if the test never
// reads any files.
//
// Ex. --dir=.. --dir=../.. --dir=../../..
// Add directories to the module root, but skip the current working
// directory which is already added by buildAndRun.
dirs := dirsToModuleRoot(result.MainDir, result.ModuleRoot)
var args []string
for _, d := range dirs[1:] {
args = append(args, "--dir="+d)
}
// Some tests create temp directories using os.MkdirTemp or via
// t.TempDir(). Create a writeable directory and map it to the
// default tempDir environment variable: TMPDIR.
// create a new temp directory just for this run, announce it to os.TempDir() via TMPDIR
tmpdir, err := os.MkdirTemp("", "tinygotmp")
if err != nil {
return fmt.Errorf("failed to create temporary directory: %w", err)
@@ -282,8 +262,7 @@ func Test(pkgName string, stdout, stderr io.Writer, options *compileopts.Options
// TODO: add option to not delete temp dir for debugging?
defer os.RemoveAll(tmpdir)
// The below re-organizes the arguments so that the current
// directory is added last.
// Insert new argments at the front of the command line argments.
args = append(args, cmd.Args[1:]...)
cmd.Args = append(cmd.Args[:1:1], args...)
}
@@ -423,6 +402,7 @@ 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,11 +410,13 @@ 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")
}
@@ -455,6 +437,7 @@ 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 {
@@ -473,13 +456,10 @@ 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
})
}
@@ -999,7 +979,6 @@ func getDefaultPort(portFlag string, usbInterfaces []string) (port string, err e
}
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
@@ -1021,8 +1000,6 @@ 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
@@ -1034,10 +1011,18 @@ 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
} else {
// No preferred ports found. Fall back to other serial ports
// available in the system.
ports = secondaryPorts
}
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()
}
}
default:
return "", errors.New("unable to search for a default USB device to be flashed on this OS")
@@ -1052,9 +1037,7 @@ func getDefaultPort(portFlag string, usbInterfaces []string) (port string, err e
}
if len(portCandidates) == 0 {
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 {
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, ", "))
@@ -1119,7 +1102,6 @@ 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")+")")
@@ -1316,12 +1298,6 @@ 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")
@@ -1336,8 +1312,6 @@ 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" {
@@ -1404,7 +1378,6 @@ func main() {
GOARCH: goenv.Get("GOARCH"),
GOARM: goenv.Get("GOARM"),
Target: *target,
StackSize: stackSize,
Opt: *opt,
GC: *gc,
PanicStrategy: *panicStrategy,
@@ -1427,8 +1400,6 @@ func main() {
OpenOCDCommands: ocdCommands,
LLVMFeatures: *llvmFeatures,
PrintJSON: flagJSON,
Monitor: *monitor,
BaudRate: *baudrate,
}
if *printCommands {
options.PrintCommands = printCommand
@@ -1619,9 +1590,6 @@ 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
View File
@@ -1,106 +0,0 @@
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
}
+2 -2
View File
@@ -1,5 +1,5 @@
//go:build nrf || stm32 || (sam && atsamd51) || (sam && atsame5x)
// +build nrf stm32 sam,atsamd51 sam,atsame5x
//go:build stm32 || (sam && atsamd51) || (sam && atsame5x)
// +build stm32 sam,atsamd51 sam,atsame5x
package rand
+49
View File
@@ -0,0 +1,49 @@
// 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)
}
}
-23
View File
@@ -1,23 +0,0 @@
// 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)
}
}
+11 -9
View File
@@ -21,14 +21,12 @@ $ tinygo build -o ./wasm.wasm -target wasm ./main/main.go
This creates a `wasm.wasm` file, which we can load in JavaScript and execute in
a browser.
Next, choose which example you want to use:
* [callback](callback): Defines and configures callbacks in Wasm.
* [export](export): Defines callbacks in Wasm, but configures them in JavaScript.
* [invoke](invoke): Invokes a function defined in JavaScript from Wasm.
* [main](main): Prints a message to the JavaScript console from Wasm.
* [slices](slices): Splits an Array defined in JavaScript from Wasm.
This examples folder contains two examples that can be built using `make`:
```bash
$ make export
```
Let's say you chose [main](main), you'd build it like so:
```bash
$ make main
```
@@ -44,8 +42,12 @@ Serving ./html on http://localhost:8080
Use your web browser to visit http://localhost:8080.
* Tip: Open the browser development tools (e.g. Right-click, Inspect in
FireFox) to see console output.
* The wasm "export" example displays a simple math equation using HTML, with
the result calculated dynamically using WebAssembly. Changing any of the
values on the left hand side triggers the exported wasm `update` function to
recalculate the result.
* The wasm "main" example uses `println` to write to your browser JavaScript
console. You may need to open the browser development tools console to see it.
## How it works
-2
View File
@@ -8,12 +8,10 @@ import (
var a, b int
func main() {
wait := make(chan struct{}, 0)
document := js.Global().Get("document")
document.Call("getElementById", "a").Set("oninput", updater(&a))
document.Call("getElementById", "b").Set("oninput", updater(&b))
update()
<-wait
}
func updater(n *int) js.Func {
-4
View File
@@ -2,16 +2,12 @@
.functype start_unwind (i32) -> ()
.import_module start_unwind, asyncify
.import_name start_unwind, start_unwind
.functype stop_unwind () -> ()
.import_module stop_unwind, asyncify
.import_name stop_unwind, stop_unwind
.functype start_rewind (i32) -> ()
.import_module start_rewind, asyncify
.import_name start_rewind, start_rewind
.functype stop_rewind () -> ()
.import_module stop_rewind, asyncify
.import_name stop_rewind, stop_rewind
.global tinygo_unwind
.hidden tinygo_unwind
+2 -28
View File
@@ -1,8 +1,5 @@
// Windows on amd64 has a slightly different ABI than other (*nix) systems.
// Therefore, assembly functions need to be tweaked slightly.
//
// The calling convention is described here:
// https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170
.section .text.tinygo_startTask,"ax"
.global tinygo_startTask
@@ -20,9 +17,8 @@ tinygo_startTask:
// Branch to the "goroutine start" function.
callq *%r12
// After return, exit this goroutine.
// This has to be a call, not a jump, to keep the stack correctly aligned.
callq tinygo_pause
// After return, exit this goroutine. This is a tail call.
jmp tinygo_pause
.global tinygo_swapTask
.section .text.tinygo_swapTask,"ax"
@@ -39,17 +35,6 @@ tinygo_swapTask:
pushq %rsi
pushq %rdi
pushq %rbp
sub $160, %rsp
movaps %xmm6, 144(%rsp)
movaps %xmm7, 128(%rsp)
movaps %xmm8, 112(%rsp)
movaps %xmm9, 96(%rsp)
movaps %xmm10, 80(%rsp)
movaps %xmm11, 64(%rsp)
movaps %xmm12, 48(%rsp)
movaps %xmm13, 32(%rsp)
movaps %xmm14, 16(%rsp)
movaps %xmm15, 0(%rsp)
pushq %rbx
// Save the current stack pointer in oldStack.
@@ -60,17 +45,6 @@ tinygo_swapTask:
// Load saved register from the new stack.
popq %rbx
movaps 0(%rsp), %xmm15
movaps 16(%rsp), %xmm14
movaps 32(%rsp), %xmm13
movaps 48(%rsp), %xmm12
movaps 64(%rsp), %xmm11
movaps 80(%rsp), %xmm10
movaps 96(%rsp), %xmm9
movaps 112(%rsp), %xmm8
movaps 128(%rsp), %xmm7
movaps 144(%rsp), %xmm6
add $160, %rsp
popq %rbp
popq %rdi
popq %rsi
@@ -13,27 +13,8 @@ var systemStack uintptr
// calleeSavedRegs is the list of registers that must be saved and restored when
// switching between tasks. Also see task_stack_amd64_windows.S that relies on
// the exact layout of this struct.
// The calling convention is described here:
// https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170
// Most importantly, these are the registers we need to save/restore:
//
// > The x64 ABI considers registers RBX, RBP, RDI, RSI, RSP, R12, R13, R14,
// > R15, and XMM6-XMM15 nonvolatile. They must be saved and restored by a
// > function that uses them.
type calleeSavedRegs struct {
// Note: rbx is placed here so that the stack is correctly aligned when
// loading/storing the xmm registers.
rbx uintptr
xmm15 [2]uint64
xmm14 [2]uint64
xmm13 [2]uint64
xmm12 [2]uint64
xmm11 [2]uint64
xmm10 [2]uint64
xmm9 [2]uint64
xmm8 [2]uint64
xmm7 [2]uint64
xmm6 [2]uint64
rbp uintptr
rdi uintptr
rsi uintptr
+1 -1
View File
@@ -7,7 +7,7 @@
package machine
// used to reset into bootloader
const resetMagicValue = 0x07738135
const RESET_MAGIC_VALUE = 0x07738135
// GPIO Pins
const (
+1 -1
View File
@@ -7,7 +7,7 @@
package machine
// used to reset into bootloader
const resetMagicValue = 0x07738135
const RESET_MAGIC_VALUE = 0x07738135
// GPIO Pins
const (
+1 -1
View File
@@ -7,7 +7,7 @@
package machine
// used to reset into bootloader
const resetMagicValue = 0x07738135
const RESET_MAGIC_VALUE = 0x07738135
// GPIO Pins
const (
+1 -1
View File
@@ -4,7 +4,7 @@
package machine
// used to reset into bootloader
const resetMagicValue = 0x07738135
const RESET_MAGIC_VALUE = 0x07738135
// GPIO Pins - Digital Low
const (
+6 -6
View File
@@ -12,9 +12,9 @@ const (
const (
PB0 = portB + 0
PB1 = portB + 1 // peripherals: Timer1 channel A
PB2 = portB + 2 // peripherals: Timer1 channel B
PB3 = portB + 3 // peripherals: Timer2 channel A
PB1 = portB + 1
PB2 = portB + 2
PB3 = portB + 3
PB4 = portB + 4
PB5 = portB + 5
PB6 = portB + 6
@@ -30,9 +30,9 @@ const (
PD0 = portD + 0
PD1 = portD + 1
PD2 = portD + 2
PD3 = portD + 3 // peripherals: Timer2 channel B
PD3 = portD + 3
PD4 = portD + 4
PD5 = portD + 5 // peripherals: Timer0 channel B
PD6 = portD + 6 // peripherals: Timer0 channel A
PD5 = portD + 5
PD6 = portD + 6
PD7 = portD + 7
)
+34 -34
View File
@@ -10,38 +10,38 @@ func CPUFrequency() uint32 {
// Hardware pins
const (
PA00 Pin = 0 // peripherals: TCC2 channel 0
PA01 Pin = 1 // peripherals: TCC2 channel 1
PA00 Pin = 0
PA01 Pin = 1
PA02 Pin = 2
PA03 Pin = 3
PA04 Pin = 4 // peripherals: TCC0 channel 0
PA05 Pin = 5 // peripherals: TCC0 channel 1
PA06 Pin = 6 // peripherals: TCC1 channel 0
PA07 Pin = 7 // peripherals: TCC1 channel 1
PA08 Pin = 8 // peripherals: TCC0 channel 0, TCC1 channel 2
PA09 Pin = 9 // peripherals: TCC0 channel 1, TCC1 channel 3
PA10 Pin = 10 // peripherals: TCC1 channel 0, TCC0 channel 2
PA11 Pin = 11 // peripherals: TCC1 channel 1, TCC0 channel 3
PA12 Pin = 12 // peripherals: TCC2 channel 0, TCC0 channel 2
PA13 Pin = 13 // peripherals: TCC2 channel 1, TCC0 channel 3
PA14 Pin = 14 // peripherals: TCC0 channel 0
PA15 Pin = 15 // peripherals: TCC0 channel 1
PA16 Pin = 16 // peripherals: TCC2 channel 0, TCC0 channel 2
PA17 Pin = 17 // peripherals: TCC2 channel 1, TCC0 channel 3
PA18 Pin = 18 // peripherals: TCC0 channel 2
PA19 Pin = 19 // peripherals: TCC0 channel 3
PA20 Pin = 20 // peripherals: TCC0 channel 2
PA21 Pin = 21 // peripherals: TCC0 channel 3
PA22 Pin = 22 // peripherals: TCC0 channel 0
PA23 Pin = 23 // peripherals: TCC0 channel 1
PA24 Pin = 24 // peripherals: TCC1 channel 2
PA25 Pin = 25 // peripherals: TCC1 channel 3
PA04 Pin = 4
PA05 Pin = 5
PA06 Pin = 6
PA07 Pin = 7
PA08 Pin = 8
PA09 Pin = 9
PA10 Pin = 10
PA11 Pin = 11
PA12 Pin = 12
PA13 Pin = 13
PA14 Pin = 14
PA15 Pin = 15
PA16 Pin = 16
PA17 Pin = 17
PA18 Pin = 18
PA19 Pin = 19
PA20 Pin = 20
PA21 Pin = 21
PA22 Pin = 22
PA23 Pin = 23
PA24 Pin = 24
PA25 Pin = 25
PA26 Pin = 26
PA27 Pin = 27
PA28 Pin = 28
PA29 Pin = 29
PA30 Pin = 30 // peripherals: TCC1 channel 0
PA31 Pin = 31 // peripherals: TCC1 channel 1
PA30 Pin = 30
PA31 Pin = 31
PB00 Pin = 32
PB01 Pin = 33
PB02 Pin = 34
@@ -52,14 +52,14 @@ const (
PB07 Pin = 39
PB08 Pin = 40
PB09 Pin = 41
PB10 Pin = 42 // peripherals: TCC0 channel 0
PB11 Pin = 43 // peripherals: TCC0 channel 1
PB12 Pin = 44 // peripherals: TCC0 channel 2
PB13 Pin = 45 // peripherals: TCC0 channel 3
PB10 Pin = 42
PB11 Pin = 43
PB12 Pin = 44
PB13 Pin = 45
PB14 Pin = 46
PB15 Pin = 47
PB16 Pin = 48 // peripherals: TCC0 channel 0
PB17 Pin = 49 // peripherals: TCC0 channel 1
PB16 Pin = 48
PB17 Pin = 49
PB18 Pin = 50
PB19 Pin = 51
PB20 Pin = 52
@@ -72,6 +72,6 @@ const (
PB27 Pin = 59
PB28 Pin = 60
PB29 Pin = 61
PB30 Pin = 62 // peripherals: TCC0 channel 0, TCC1 channel 2
PB31 Pin = 63 // peripherals: TCC0 channel 1, TCC1 channel 3
PB30 Pin = 62
PB31 Pin = 63
)
+1 -1
View File
@@ -8,7 +8,7 @@ import (
)
// Definition for compatibility, but not used
const resetMagicValue = 0x00000000
const RESET_MAGIC_VALUE = 0x00000000
const (
LED = PC18
+1 -1
View File
@@ -4,7 +4,7 @@
package machine
// used to reset into bootloader
const resetMagicValue = 0xf01669ef
const RESET_MAGIC_VALUE = 0xf01669ef
// GPIO Pins
const (
+1 -1
View File
@@ -4,7 +4,7 @@
package machine
// used to reset into bootloader
const resetMagicValue = 0xf01669ef
const RESET_MAGIC_VALUE = 0xf01669ef
// GPIO Pins
const (
+1 -1
View File
@@ -8,7 +8,7 @@ import (
)
// used to reset into bootloader
const resetMagicValue = 0xf01669ef
const RESET_MAGIC_VALUE = 0xf01669ef
// GPIO Pins
const (
+1 -1
View File
@@ -4,7 +4,7 @@
package machine
// used to reset into bootloader
const resetMagicValue = 0xf01669ef
const RESET_MAGIC_VALUE = 0xf01669ef
// GPIO Pins
const (
+1 -1
View File
@@ -245,7 +245,7 @@ const (
// Other peripheral constants
const (
resetMagicValue = 0xF01669EF // Used to reset into bootloader
RESET_MAGIC_VALUE = 0xF01669EF // Used to reset into bootloader
)
// USB CDC pins
+1 -1
View File
@@ -4,7 +4,7 @@
package machine
// used to reset into bootloader
const resetMagicValue = 0xf01669ef
const RESET_MAGIC_VALUE = 0xf01669ef
// GPIO Pins
const (
+1 -1
View File
@@ -4,7 +4,7 @@
package machine
// used to reset into bootloader
const resetMagicValue = 0xf01669ef
const RESET_MAGIC_VALUE = 0xf01669ef
// GPIO Pins
const (
+1 -1
View File
@@ -4,7 +4,7 @@
package machine
// used to reset into bootloader
const resetMagicValue = 0xF01669EF
const RESET_MAGIC_VALUE = 0xF01669EF
// Digital pins
const (
+1 -1
View File
@@ -4,7 +4,7 @@
package machine
// used to reset into bootloader
const resetMagicValue = 0xf01669ef
const RESET_MAGIC_VALUE = 0xf01669ef
// GPIO Pins
const (
+1 -1
View File
@@ -7,7 +7,7 @@
package machine
// used to reset into bootloader
const resetMagicValue = 0x07738135
const RESET_MAGIC_VALUE = 0x07738135
// Note: On the P1AM-100, pins D8, D9, D10, A3, and A4 are used for
// communication with the base controller.
+1 -1
View File
@@ -4,7 +4,7 @@
package machine
// used to reset into bootloader
const resetMagicValue = 0xf01669ef
const RESET_MAGIC_VALUE = 0xf01669ef
// GPIO Pins
const (
+1 -1
View File
@@ -4,7 +4,7 @@
package machine
// used to reset into bootloader
const resetMagicValue = 0xf01669ef
const RESET_MAGIC_VALUE = 0xf01669ef
// GPIO Pins
const (
+1 -1
View File
@@ -4,7 +4,7 @@
package machine
// used to reset into bootloader
const resetMagicValue = 0xf01669ef
const RESET_MAGIC_VALUE = 0xf01669ef
// GPIO Pins
const (
+1 -1
View File
@@ -4,7 +4,7 @@
package machine
// used to reset into bootloader
const resetMagicValue = 0xf01669ef
const RESET_MAGIC_VALUE = 0xf01669ef
// GPIO Pins
const (
+4 -3
View File
@@ -36,9 +36,10 @@ const (
)
const (
NEOPIXEL = GPIO12
NEOPIXELS = GPIO12
WS2812 = GPIO12
NEOPIXEL_POWER = GPIO11
NEOPIXELS_POWER = GPIO11
LED = GPIO20
)
// I2C Pins.
@@ -115,5 +116,5 @@ const (
var (
usb_VID uint16 = 0x239A
usb_PID uint16 = 0x80F7
usb_PID uint16 = 0x80F1
)
+1 -1
View File
@@ -4,7 +4,7 @@
package machine
// used to reset into bootloader
const resetMagicValue = 0xf01669ef
const RESET_MAGIC_VALUE = 0xf01669ef
// GPIO Pins
const (
+1 -1
View File
@@ -4,7 +4,7 @@
package machine
// used to reset into bootloader
const resetMagicValue = 0xf01669ef
const RESET_MAGIC_VALUE = 0xf01669ef
const (
ADC0 = A0
+1 -1
View File
@@ -104,7 +104,7 @@ const (
var (
usb_VID uint16 = 0x2886
usb_PID uint16 = 0x8045
usb_PID uint16 = 0x0045
)
var (
+1 -1
View File
@@ -4,7 +4,7 @@
package machine
// used to reset into bootloader
const resetMagicValue = 0xf01669ef
const RESET_MAGIC_VALUE = 0xf01669ef
// GPIO Pins
const (
-2
View File
@@ -8,8 +8,6 @@ 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
-7
View File
@@ -18,13 +18,6 @@ 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.
+1 -1
View File
@@ -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 = 100 * KHz
config.Frequency = TWI_FREQ_100KHZ
}
// Activate internal pullups for twi.
+15 -15
View File
@@ -38,10 +38,10 @@ const (
PB1 = portB + 1
PB2 = portB + 2
PB3 = portB + 3
PB4 = portB + 4 // peripherals: Timer2 channel A
PB5 = portB + 5 // peripherals: Timer1 channel A
PB6 = portB + 6 // peripherals: Timer1 channel B
PB7 = portB + 7 // peripherals: Timer0 channel A
PB4 = portB + 4
PB5 = portB + 5
PB6 = portB + 6
PB7 = portB + 7
PC0 = portC + 0
PC1 = portC + 1
PC2 = portC + 2
@@ -57,9 +57,9 @@ const (
PD7 = portD + 7
PE0 = portE + 0
PE1 = portE + 1
PE3 = portE + 3 // peripherals: Timer3 channel A
PE4 = portE + 4 // peripherals: Timer3 channel B
PE5 = portE + 5 // peripherals: Timer3 channel C
PE3 = portE + 3
PE4 = portE + 4
PE5 = portE + 5
PE6 = portE + 6
PF0 = portF + 0
PF1 = portF + 1
@@ -72,13 +72,13 @@ const (
PG0 = portG + 0
PG1 = portG + 1
PG2 = portG + 2
PG5 = portG + 5 // peripherals: Timer0 channel B
PG5 = portG + 5
PH0 = portH + 0
PH1 = portH + 1
PH3 = portH + 3 // peripherals: Timer4 channel A
PH4 = portH + 4 // peripherals: Timer4 channel B
PH5 = portH + 5 // peripherals: Timer4 channel C
PH6 = portH + 6 // peripherals: Timer0 channel B
PH3 = portH + 3
PH4 = portH + 4
PH5 = portH + 5
PH6 = portH + 6
PJ0 = portJ + 0
PJ1 = portJ + 1
PK0 = portK + 0
@@ -92,9 +92,9 @@ const (
PL0 = portL + 0
PL1 = portL + 1
PL2 = portL + 2
PL3 = portL + 3 // peripherals: Timer5 channel A
PL4 = portL + 4 // peripherals: Timer5 channel B
PL5 = portL + 5 // peripherals: Timer5 channel C
PL3 = portL + 3
PL4 = portL + 4
PL5 = portL + 5
PL6 = portL + 6
PL7 = portL + 7
)
+7 -2
View File
@@ -10,6 +10,7 @@ package machine
import (
"device/arm"
"device/sam"
"errors"
"runtime/interrupt"
"unsafe"
)
@@ -676,7 +677,7 @@ const i2cTimeout = 1000
func (i2c *I2C) Configure(config I2CConfig) error {
// Default I2C bus speed is 100 kHz.
if config.Frequency == 0 {
config.Frequency = 100 * KHz
config.Frequency = TWI_FREQ_100KHZ
}
if config.SDA == 0 && config.SCL == 0 {
config.SDA = SDA_PIN
@@ -1273,6 +1274,10 @@ 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.
@@ -1735,7 +1740,7 @@ func EnterBootloader() {
// Perform magic reset into bootloader, as mentioned in
// https://github.com/arduino/ArduinoCore-samd/issues/197
*(*uint32)(unsafe.Pointer(uintptr(0x20007FFC))) = resetMagicValue
*(*uint32)(unsafe.Pointer(uintptr(0x20007FFC))) = RESET_MAGIC_VALUE
arm.SystemReset()
}
+71 -66
View File
@@ -10,6 +10,7 @@ package machine
import (
"device/arm"
"device/sam"
"errors"
"runtime/interrupt"
"unsafe"
)
@@ -77,86 +78,86 @@ const (
PA05 Pin = 5
PA06 Pin = 6
PA07 Pin = 7
PA08 Pin = 8 // peripherals: TCC0 channel 0, TCC1 channel 4
PA09 Pin = 9 // peripherals: TCC0 channel 1, TCC1 channel 5
PA10 Pin = 10 // peripherals: TCC0 channel 2, TCC1 channel 6
PA11 Pin = 11 // peripherals: TCC0 channel 3, TCC1 channel 7
PA12 Pin = 12 // peripherals: TCC0 channel 6, TCC1 channel 2
PA13 Pin = 13 // peripherals: TCC0 channel 7, TCC1 channel 3
PA14 Pin = 14 // peripherals: TCC2 channel 0, TCC1 channel 2
PA15 Pin = 15 // peripherals: TCC2 channel 1, TCC1 channel 3
PA16 Pin = 16 // peripherals: TCC1 channel 0, TCC0 channel 4
PA17 Pin = 17 // peripherals: TCC1 channel 1, TCC0 channel 5
PA18 Pin = 18 // peripherals: TCC1 channel 2, TCC0 channel 6
PA19 Pin = 19 // peripherals: TCC1 channel 3, TCC0 channel 7
PA20 Pin = 20 // peripherals: TCC1 channel 4, TCC0 channel 0
PA21 Pin = 21 // peripherals: TCC1 channel 5, TCC0 channel 1
PA22 Pin = 22 // peripherals: TCC1 channel 6, TCC0 channel 2
PA23 Pin = 23 // peripherals: TCC1 channel 7, TCC0 channel 3
PA24 Pin = 24 // peripherals: TCC2 channel 2
PA25 Pin = 25 // peripherals: TCC2 channel 3
PA08 Pin = 8
PA09 Pin = 9
PA10 Pin = 10
PA11 Pin = 11
PA12 Pin = 12
PA13 Pin = 13
PA14 Pin = 14
PA15 Pin = 15
PA16 Pin = 16
PA17 Pin = 17
PA18 Pin = 18
PA19 Pin = 19
PA20 Pin = 20
PA21 Pin = 21
PA22 Pin = 22
PA23 Pin = 23
PA24 Pin = 24
PA25 Pin = 25
PA26 Pin = 26
PA27 Pin = 27
PA28 Pin = 28
PA29 Pin = 29
PA30 Pin = 30 // peripherals: TCC2 channel 0
PA31 Pin = 31 // peripherals: TCC2 channel 1
PA30 Pin = 30
PA31 Pin = 31
PB00 Pin = 32
PB01 Pin = 33
PB02 Pin = 34 // peripherals: TCC2 channel 2
PB03 Pin = 35 // peripherals: TCC2 channel 3
PB02 Pin = 34
PB03 Pin = 35
PB04 Pin = 36
PB05 Pin = 37
PB06 Pin = 38
PB07 Pin = 39
PB08 Pin = 40
PB09 Pin = 41
PB10 Pin = 42 // peripherals: TCC0 channel 4, TCC1 channel 0
PB11 Pin = 43 // peripherals: TCC0 channel 5, TCC1 channel 1
PB12 Pin = 44 // peripherals: TCC3 channel 0, TCC0 channel 0
PB13 Pin = 45 // peripherals: TCC3 channel 1, TCC0 channel 1
PB14 Pin = 46 // peripherals: TCC4 channel 0, TCC0 channel 2
PB15 Pin = 47 // peripherals: TCC4 channel 1, TCC0 channel 3
PB16 Pin = 48 // peripherals: TCC3 channel 0, TCC0 channel 4
PB17 Pin = 49 // peripherals: TCC3 channel 1, TCC0 channel 5
PB18 Pin = 50 // peripherals: TCC1 channel 0
PB19 Pin = 51 // peripherals: TCC1 channel 1
PB20 Pin = 52 // peripherals: TCC1 channel 2
PB21 Pin = 53 // peripherals: TCC1 channel 3
PB10 Pin = 42
PB11 Pin = 43
PB12 Pin = 44
PB13 Pin = 45
PB14 Pin = 46
PB15 Pin = 47
PB16 Pin = 48
PB17 Pin = 49
PB18 Pin = 50
PB19 Pin = 51
PB20 Pin = 52
PB21 Pin = 53
PB22 Pin = 54
PB23 Pin = 55
PB24 Pin = 56
PB25 Pin = 57
PB26 Pin = 58 // peripherals: TCC1 channel 2
PB27 Pin = 59 // peripherals: TCC1 channel 3
PB28 Pin = 60 // peripherals: TCC1 channel 4
PB29 Pin = 61 // peripherals: TCC1 channel 5
PB30 Pin = 62 // peripherals: TCC4 channel 0, TCC0 channel 6
PB31 Pin = 63 // peripherals: TCC4 channel 1, TCC0 channel 7
PB26 Pin = 58
PB27 Pin = 59
PB28 Pin = 60
PB29 Pin = 61
PB30 Pin = 62
PB31 Pin = 63
PC00 Pin = 64
PC01 Pin = 65
PC02 Pin = 66
PC03 Pin = 67
PC04 Pin = 68 // peripherals: TCC0 channel 0
PC05 Pin = 69 // peripherals: TCC0 channel 1
PC04 Pin = 68
PC05 Pin = 69
PC06 Pin = 70
PC07 Pin = 71
PC08 Pin = 72
PC09 Pin = 73
PC10 Pin = 74 // peripherals: TCC0 channel 0, TCC1 channel 4
PC11 Pin = 75 // peripherals: TCC0 channel 1, TCC1 channel 5
PC12 Pin = 76 // peripherals: TCC0 channel 2, TCC1 channel 6
PC13 Pin = 77 // peripherals: TCC0 channel 3, TCC1 channel 7
PC14 Pin = 78 // peripherals: TCC0 channel 4, TCC1 channel 0
PC15 Pin = 79 // peripherals: TCC0 channel 5, TCC1 channel 1
PC16 Pin = 80 // peripherals: TCC0 channel 0
PC17 Pin = 81 // peripherals: TCC0 channel 1
PC18 Pin = 82 // peripherals: TCC0 channel 2
PC19 Pin = 83 // peripherals: TCC0 channel 3
PC20 Pin = 84 // peripherals: TCC0 channel 4
PC21 Pin = 85 // peripherals: TCC0 channel 5
PC22 Pin = 86 // peripherals: TCC0 channel 6
PC23 Pin = 87 // peripherals: TCC0 channel 7
PC10 Pin = 74
PC11 Pin = 75
PC12 Pin = 76
PC13 Pin = 77
PC14 Pin = 78
PC15 Pin = 79
PC16 Pin = 80
PC17 Pin = 81
PC18 Pin = 82
PC19 Pin = 83
PC20 Pin = 84
PC21 Pin = 85
PC22 Pin = 86
PC23 Pin = 87
PC24 Pin = 88
PC25 Pin = 89
PC26 Pin = 90
@@ -173,20 +174,20 @@ const (
PD05 Pin = 101
PD06 Pin = 102
PD07 Pin = 103
PD08 Pin = 104 // peripherals: TCC0 channel 1
PD09 Pin = 105 // peripherals: TCC0 channel 2
PD10 Pin = 106 // peripherals: TCC0 channel 3
PD11 Pin = 107 // peripherals: TCC0 channel 4
PD12 Pin = 108 // peripherals: TCC0 channel 5
PD13 Pin = 109 // peripherals: TCC0 channel 6
PD08 Pin = 104
PD09 Pin = 105
PD10 Pin = 106
PD11 Pin = 107
PD12 Pin = 108
PD13 Pin = 109
PD14 Pin = 110
PD15 Pin = 111
PD16 Pin = 112
PD17 Pin = 113
PD18 Pin = 114
PD19 Pin = 115
PD20 Pin = 116 // peripherals: TCC1 channel 0
PD21 Pin = 117 // peripherals: TCC1 channel 1
PD20 Pin = 116
PD21 Pin = 117
PD22 Pin = 118
PD23 Pin = 119
PD24 Pin = 120
@@ -1150,7 +1151,7 @@ const i2cTimeout = 1000
func (i2c *I2C) Configure(config I2CConfig) error {
// Default I2C bus speed is 100 kHz.
if config.Frequency == 0 {
config.Frequency = 100 * KHz
config.Frequency = TWI_FREQ_100KHZ
}
// Use default I2C pins if not set.
@@ -1526,6 +1527,10 @@ 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.
@@ -1975,7 +1980,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))) = resetMagicValue
*(*uint32)(unsafe.Pointer(uintptr(0x20000000 + HSRAM_SIZE - 4))) = RESET_MAGIC_VALUE
arm.SystemReset()
}
+14 -2
View File
@@ -59,9 +59,12 @@ type PinChange uint8
// Pin change interrupt constants for SetInterrupt.
const (
PinRising PinChange = iota + 1
PinNoInterrupt PinChange = iota
PinRising
PinFalling
PinToggle
PinLowLevel
PinHighLevel
)
// Configure this pin with the given configuration.
@@ -187,7 +190,7 @@ func (p Pin) SetInterrupt(change PinChange, callback func(Pin)) (err error) {
return ErrInvalidInputPin
}
if callback == nil {
if callback == nil || change == PinNoInterrupt {
// Disable this pin interrupt
p.pin().ClearBits(esp.GPIO_PIN_PIN_INT_TYPE_Msk | esp.GPIO_PIN_PIN_INT_ENA_Msk)
@@ -261,6 +264,15 @@ 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
+1 -1
View File
@@ -231,7 +231,7 @@ type I2CConfig struct {
func (i2c *I2C) Configure(config I2CConfig) error {
var i2cClockFrequency uint32 = 32000000
if config.Frequency == 0 {
config.Frequency = 100 * KHz
config.Frequency = TWI_FREQ_100KHZ
}
if config.SDA == 0 && config.SCL == 0 {
+5 -11
View File
@@ -23,17 +23,11 @@ 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
@@ -95,10 +89,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:
@@ -523,7 +517,7 @@ type I2CConfig struct {
func (i2c *I2C) Configure(config I2CConfig) error {
if config.Frequency == 0 {
config.Frequency = 100 * KHz
config.Frequency = TWI_FREQ_100KHZ
}
if config.SDA == 0 && config.SCL == 0 {
+9 -13
View File
@@ -21,8 +21,8 @@ func CPUFrequency() uint32 {
const (
// GPIO
PinInput PinMode = iota
PinInputPullup
PinInputPulldown
PinInputPullUp
PinInputPullDown
PinOutput
PinOutputOpenDrain
PinDisable
@@ -45,16 +45,12 @@ const (
PinModeI2CSCL
)
// Deprecated: use PinInputPullup and PinInputPulldown instead.
const (
PinInputPullUp = PinInputPullup
PinInputPullDown = PinInputPulldown
)
type PinChange uint8
const (
PinRising PinChange = iota + 2
PinLow PinChange = iota
PinHigh
PinRising
PinFalling
PinToggle
)
@@ -263,11 +259,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)
@@ -391,7 +387,7 @@ func (p Pin) SetInterrupt(change PinChange, callback func(Pin)) error {
mask := p.getMask()
if nil != callback {
switch change {
case PinRising, PinFalling:
case PinLow, PinHigh, PinRising, PinFalling:
gpio.EDGE_SEL.ClearBits(mask)
var reg *volatile.Register32
var pos uint8
@@ -750,7 +746,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 {
+16 -7
View File
@@ -10,6 +10,15 @@ 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")
@@ -165,7 +174,7 @@ func (i2c *I2C) Configure(config I2CConfig) {
freq := config.Frequency
if 0 == freq {
freq = 100 * KHz
freq = TWI_FREQ_DEFAULT
}
// reset clock and registers, and enable LPI2C module interface
@@ -296,7 +305,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 = (24MHz/(2^pre))/(CLKLO+1 + CLKHI+1 + FLOOR((2+FILTSCL)/(2^pre)))
// baud rate = (TWI_FREQ_BUS/(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 {
@@ -305,9 +314,9 @@ func (i2c *I2C) setFrequency(freq uint32) {
for clkHi := uint32(1); clkHi < 32; clkHi++ {
var absError, rate uint32
if clkHi == 1 {
rate = (24 * MHz / pre) / (1 + 3 + 2 + 2/pre)
rate = (TWI_FREQ_BUS / pre) / (1 + 3 + 2 + 2/pre)
} else {
rate = (24 * MHz / pre) / (3*clkHi + 2 + 2/pre)
rate = (TWI_FREQ_BUS / pre) / (3*clkHi + 2 + 2/pre)
}
if freq > rate {
absError = freq - rate
@@ -361,15 +370,15 @@ func (i2c *I2C) setFrequency(freq uint32) {
mcfgr2, mcfgr3 uint32
)
const i2cClockStretchTimeout = 15000 // microseconds
if freq >= 5*MHz {
if freq >= TWI_FREQ_5MHZ {
// I2C UltraFastMode 5 MHz
mcfgr2 = 0 // disable glitch filters and timeout for UltraFastMode
mcfgr3 = 0 //
} else if freq >= 1*MHz {
} else if freq >= TWI_FREQ_1MHZ {
// I2C FastModePlus 1 MHz
mcfgr2 = filtsda(1) | filtscl(1) | busidle(2400) // 100us timeout
mcfgr3 = pinlow(i2cClockStretchTimeout*24/256 + 1)
} else if freq >= 400*KHz {
} else if freq >= TWI_FREQ_400KHZ {
// I2C FastMode 400 kHz
mcfgr2 = filtsda(2) | filtscl(2) | busidle(3600) // 150us timeout
mcfgr3 = pinlow(i2cClockStretchTimeout*24/256 + 1)
+2 -2
View File
@@ -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
}
+7 -40
View File
@@ -5,10 +5,15 @@ 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 (
@@ -225,7 +230,7 @@ func (i2c *I2C) Configure(config I2CConfig) error {
// Default I2C bus speed is 100 kHz.
if config.Frequency == 0 {
config.Frequency = 100 * KHz
config.Frequency = TWI_FREQ_100KHZ
}
// Default I2C pins if not set.
if config.SDA == 0 && config.SCL == 0 {
@@ -248,7 +253,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 >= 400*KHz {
if config.Frequency == TWI_FREQ_400KHZ {
i2c.Bus.FREQUENCY.Set(nrf.TWI_FREQUENCY_FREQUENCY_K400)
} else {
i2c.Bus.FREQUENCY.Set(nrf.TWI_FREQUENCY_FREQUENCY_K100)
@@ -345,41 +350,3 @@ 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 (
dfuMagicSerialOnlyReset = 0x4e
dfuMagicUF2Reset = 0x57
dfuMagicOTAReset = 0xA8
DFU_MAGIC_SERIAL_ONLY_RESET = 0x4e
DFU_MAGIC_UF2_RESET = 0x57
DFU_MAGIC_OTA_RESET = 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(dfuMagicSerialOnlyReset)
nrf.POWER.GPREGRET.Set(DFU_MAGIC_SERIAL_ONLY_RESET)
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(dfuMagicUF2Reset)
nrf.POWER.GPREGRET.Set(DFU_MAGIC_UF2_RESET)
arm.SystemReset()
}
@@ -34,6 +34,6 @@ func EnterUF2Bootloader() {
// flashed via an OTA update
func EnterOTABootloader() {
arm.DisableInterrupts()
nrf.POWER.GPREGRET.Set(dfuMagicOTAReset)
nrf.POWER.GPREGRET.Set(DFU_MAGIC_OTA_RESET)
arm.SystemReset()
}
+4 -10
View File
@@ -42,19 +42,13 @@ 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
@@ -229,11 +223,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)
+2 -2
View File
@@ -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()
+30 -30
View File
@@ -11,36 +11,36 @@ const deviceName = rp.Device
const (
// GPIO pins
GPIO0 Pin = 0 // peripherals: PWM0 channel A
GPIO1 Pin = 1 // peripherals: PWM0 channel B
GPIO2 Pin = 2 // peripherals: PWM1 channel A
GPIO3 Pin = 3 // peripherals: PWM1 channel B
GPIO4 Pin = 4 // peripherals: PWM2 channel A
GPIO5 Pin = 5 // peripherals: PWM2 channel B
GPIO6 Pin = 6 // peripherals: PWM3 channel A
GPIO7 Pin = 7 // peripherals: PWM3 channel B
GPIO8 Pin = 8 // peripherals: PWM4 channel A
GPIO9 Pin = 9 // peripherals: PWM4 channel B
GPIO10 Pin = 10 // peripherals: PWM5 channel A
GPIO11 Pin = 11 // peripherals: PWM5 channel B
GPIO12 Pin = 12 // peripherals: PWM6 channel A
GPIO13 Pin = 13 // peripherals: PWM6 channel B
GPIO14 Pin = 14 // peripherals: PWM7 channel A
GPIO15 Pin = 15 // peripherals: PWM7 channel B
GPIO16 Pin = 16 // peripherals: PWM0 channel A
GPIO17 Pin = 17 // peripherals: PWM0 channel B
GPIO18 Pin = 18 // peripherals: PWM1 channel A
GPIO19 Pin = 19 // peripherals: PWM1 channel B
GPIO20 Pin = 20 // peripherals: PWM2 channel A
GPIO21 Pin = 21 // peripherals: PWM2 channel B
GPIO22 Pin = 22 // peripherals: PWM3 channel A
GPIO23 Pin = 23 // peripherals: PWM3 channel B
GPIO24 Pin = 24 // peripherals: PWM4 channel A
GPIO25 Pin = 25 // peripherals: PWM4 channel B
GPIO26 Pin = 26 // peripherals: PWM5 channel A
GPIO27 Pin = 27 // peripherals: PWM5 channel B
GPIO28 Pin = 28 // peripherals: PWM6 channel A
GPIO29 Pin = 29 // peripherals: PWM6 channel B
GPIO0 Pin = 0
GPIO1 Pin = 1
GPIO2 Pin = 2
GPIO3 Pin = 3
GPIO4 Pin = 4
GPIO5 Pin = 5
GPIO6 Pin = 6
GPIO7 Pin = 7
GPIO8 Pin = 8
GPIO9 Pin = 9
GPIO10 Pin = 10
GPIO11 Pin = 11
GPIO12 Pin = 12
GPIO13 Pin = 13
GPIO14 Pin = 14
GPIO15 Pin = 15
GPIO16 Pin = 16
GPIO17 Pin = 17
GPIO18 Pin = 18
GPIO19 Pin = 19
GPIO20 Pin = 20
GPIO21 Pin = 21
GPIO22 Pin = 22
GPIO23 Pin = 23
GPIO24 Pin = 24
GPIO25 Pin = 25
GPIO26 Pin = 26
GPIO27 Pin = 27
GPIO28 Pin = 28
GPIO29 Pin = 29
// Analog pins
ADC0 Pin = GPIO26
+13 -14
View File
@@ -18,7 +18,7 @@ const (
adc1_CH
adc2_CH
adc3_CH // Note: GPIO29 not broken out on pico board
adcTempSensor // Internal temperature sensor channel
ADC_TEMP_SENSOR // Internal temperature sensor channel
)
// Used to serialise ADC sampling
@@ -75,17 +75,19 @@ func (a ADC) GetADCChannel() (c ADCChannel, err error) {
return c, err
}
// Configure sets the channel's associated pin to analog input mode.
// Configure sets the channel's associated pin to analog input mode or powers on the temperature sensor for ADC_TEMP_SENSOR.
// 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
}
p, err := c.Pin()
if err != nil {
return err
}
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)
}
return nil
}
@@ -110,16 +112,13 @@ func (c ADCChannel) getVoltage() uint32 {
}
// ReadTemperature does a one-shot sample of the internal temperature sensor and returns a milli-celsius reading.
func ReadTemperature() (millicelsius int32) {
if rp.ADC.CS.Get()&rp.ADC_CS_EN == 0 {
InitADC()
// 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
}
// 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 - (int32(adcTempSensor.getVoltage())-706<<16)*581) >> 16
return (27000<<16 - (c.getVoltage()-706<<16)*581) >> 16
}
// waitForReady spins waiting for the ADC peripheral to become ready.
+5
View File
@@ -10,6 +10,11 @@ import (
"unsafe"
)
const (
KHz = 1000
MHz = 1000000
)
func CPUFrequency() uint32 {
return 125 * MHz
}
+5 -1
View File
@@ -226,8 +226,12 @@ 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 PinChange = 4 << iota
PinFalling
// Edge rising
PinRising
)
-42
View File
@@ -1,42 +0,0 @@
//go:build rp2040
// +build rp2040
// Implementation based on code located here:
// https://github.com/raspberrypi/pico-sdk/blob/master/src/rp2_common/pico_lwip/random.c
package machine
import (
"device/rp"
)
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++ {
val = (val << 8) | uint32(roscRandByte())
}
return val, nil
}
var randomByte uint8
func roscRandByte() uint8 {
var poly uint8
for i := 0; i < numberOfCycles; i++ {
if randomByte&0x80 != 0 {
poly = 0x35
} else {
poly = 0
}
randomByte = ((randomByte << 1) | uint8(rp.ROSC.GetRANDOMBIT()) ^ poly)
// TODO: delay a little because the random bit is a little slow
}
return randomByte
}
+1
View File
@@ -39,6 +39,7 @@ 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")
)
+1 -1
View File
@@ -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 = 100 * KHz
config.Frequency = TWI_FREQ_100KHZ
}
// configure I2C input clock
+57 -2
View File
@@ -1,5 +1,5 @@
//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
//go:build !baremetal || (stm32 && !stm32f7x2 && !stm32l5x2) || fe310 || k210 || (nxp && !mk66f18) || atmega
// +build !baremetal stm32,!stm32f7x2,!stm32l5x2 fe310 k210 nxp,!mk66f18 atmega
package machine
@@ -17,3 +17,58 @@ 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
}
-62
View File
@@ -1,62 +0,0 @@
//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
View File
@@ -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 uint8
type UARTParity int
const (
// ParityNone means to not use any parity checking. This is
// the most common setting.
ParityNone UARTParity = iota
ParityNone UARTParity = 0
// ParityEven means to expect that the total number of 1 bits sent
// should be an even number.
ParityEven
ParityEven UARTParity = 1
// ParityOdd means to expect that the total number of 1 bits sent
// should be an odd number.
ParityOdd
ParityOdd UARTParity = 2
)
// To implement the UART interface for a board, you must declare a concrete type as follows:
+19 -67
View File
@@ -20,46 +20,21 @@ 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 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)
heapEnd = uintptr(wasm_memory_size(0) * 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
@@ -73,67 +48,44 @@ func getCurrentStackPointer() uintptr
// otherwise.
func growHeap() bool {
// Grow memory by the available size, which means the heap size is doubled.
memorySize := wasm_memory_size(wasmMemoryIndex)
result := wasm_memory_grow(wasmMemoryIndex, memorySize)
memorySize := wasm_memory_size(0)
result := wasm_memory_grow(0, memorySize)
if result == -1 {
// Grow failed.
return false
}
setHeapEnd(uintptr(wasm_memory_size(wasmMemoryIndex) * wasmPageSize))
setHeapEnd(uintptr(wasm_memory_size(0) * 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 without colliding with
// our GC allocations.
var allocs = make(map[uintptr][]byte)
// The below functions override the default allocator of wasi-libc.
// Most functions are defined but unimplemented to make sure that if there is
// any code using them, they will get an error instead of (incorrectly) using
// the wasi-libc dlmalloc heap implementation instead. If they are needed by any
// program, they can certainly be implemented.
//export malloc
func libc_malloc(size uintptr) unsafe.Pointer {
buf := make([]byte, size)
ptr := unsafe.Pointer(&buf[0])
allocs[uintptr(ptr)] = buf
return ptr
return alloc(size, nil)
}
//export free
func libc_free(ptr unsafe.Pointer) {
if ptr == nil {
return
}
if _, ok := allocs[uintptr(ptr)]; ok {
delete(allocs, uintptr(ptr))
} else {
panic("free: invalid pointer")
}
free(ptr)
}
//export calloc
func libc_calloc(nmemb, size uintptr) unsafe.Pointer {
// No difference between calloc and malloc.
return libc_malloc(nmemb * size)
// Note: we could be even more correct here and check that nmemb * size
// doesn't overflow. However the current implementation should normally work
// fine.
return alloc(nmemb*size, nil)
}
//export realloc
func libc_realloc(oldPtr unsafe.Pointer, size uintptr) unsafe.Pointer {
// 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")
}
}
ptr := unsafe.Pointer(&buf[0])
allocs[uintptr(ptr)] = buf
return ptr
func libc_realloc(ptr unsafe.Pointer, size uintptr) unsafe.Pointer {
return realloc(ptr, size)
}
-9
View File
@@ -1,9 +0,0 @@
//go:build runtime_asserts
package runtime
// enable assertions for the garbage collector
const gcAsserts = true
// enable asserts for the scheduler
const schedulerAsserts = true
-9
View File
@@ -1,9 +0,0 @@
//go:build !runtime_asserts
package runtime
// disable assertions for the garbage collector
const gcAsserts = false
// disable assertions for the scheduler
const schedulerAsserts = false
+8 -28
View File
@@ -25,9 +25,7 @@ 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.
@@ -37,7 +35,11 @@ import (
"unsafe"
)
const gcDebug = false
// Set gcDebug to true to print debug information.
const (
gcDebug = false // print debug info
gcAsserts = gcDebug // perform sanity checks
)
// Some globals + constants for the entire GC.
@@ -286,14 +288,7 @@ 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
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()
}
GC()
} else {
// Even after garbage collection, no free memory could be found.
// Try to increase heap size.
@@ -384,13 +379,6 @@ 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...")
}
@@ -432,14 +420,12 @@ func runGC() (freeBytes uintptr) {
// Sweep phase: free all non-marked objects and unmark marked objects for
// the next collection cycle.
freeBytes = sweep()
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
@@ -582,8 +568,7 @@ func markRoot(addr, root uintptr) {
}
// Sweep goes through all memory and frees unmarked memory.
// It returns how many bytes are free in the heap after the sweep.
func sweep() (freeBytes uintptr) {
func sweep() {
freeCurrentObject := false
for block := gcBlock(0); block < endBlock; block++ {
switch block.state() {
@@ -592,13 +577,11 @@ func sweep() (freeBytes uintptr) {
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,
@@ -606,11 +589,8 @@ func sweep() (freeBytes uintptr) {
// 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
+2
View File
@@ -11,6 +11,8 @@ import (
"unsafe"
)
const gcAsserts = false // perform sanity checks
// Ever-incrementing pointer: no memory is freed.
var heapptr = heapStart
+2
View File
@@ -11,6 +11,8 @@ import (
"unsafe"
)
const gcAsserts = false // perform sanity checks
var gcTotalAlloc uint64 // for runtime.MemStats
var gcMallocs uint64
var gcFrees uint64
+2 -13
View File
@@ -10,7 +10,8 @@ import (
var ErrUnimplemented = errors.New("runtime/pprof: unimplemented")
type Profile struct{}
type Profile struct {
}
func StartCPUProfile(w io.Writer) error {
return nil
@@ -27,18 +28,6 @@ func Lookup(name string) *Profile {
return nil
}
func (p *Profile) Name() string {
return ""
}
func (p *Profile) Count() int {
return 0
}
func (p *Profile) WriteTo(w io.Writer, debug int) error {
return ErrUnimplemented
}
func Profiles() []*Profile {
return nil
}
-13
View File
@@ -1,13 +0,0 @@
// Stubs for the runtime/trace package
package trace
import (
"errors"
"io"
)
func Start(w io.Writer) error {
return errors.New("not implemented")
}
func Stop() {}
-11
View File
@@ -34,17 +34,6 @@ func (m *Map) LoadOrStore(key, value interface{}) (actual interface{}, loaded bo
return value, false
}
func (m *Map) LoadAndDelete(key interface{}) (value interface{}, loaded bool) {
m.lock.Lock()
defer m.lock.Unlock()
value, ok := m.m[key]
if !ok {
return nil, false
}
delete(m.m, key)
return value, true
}
func (m *Map) Store(key, value interface{}) {
m.lock.Lock()
defer m.lock.Unlock()
-19
View File
@@ -1,19 +0,0 @@
package sync_test
import (
"sync"
"testing"
)
func TestMapLoadAndDelete(t *testing.T) {
var sm sync.Map
sm.Store("present", "value")
if v, ok := sm.LoadAndDelete("present"); !ok || v != "value" {
t.Errorf("LoadAndDelete returned %v, %v, want value, true", v, ok)
}
if v, ok := sm.LoadAndDelete("absent"); ok || v != nil {
t.Errorf("LoadAndDelete returned %v, %v, want nil, false", v, ok)
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"inherits": ["nrf52840", "nrf52840-s140v6-uf2"],
"build-tags": ["circuitplay_bluefruit"],
"serial-port": ["acm:239a:8045"],
"serial-port": ["acm:239a:8045", "acm:239a:45"],
"msd-volume-name": "CPLAYBTBOOT"
}
+1 -1
View File
@@ -3,7 +3,7 @@
"build-tags": ["circuitplay_express"],
"flash-1200-bps-reset": "true",
"flash-method": "msd",
"serial-port": ["acm:239a:8018"],
"serial-port": ["acm:239a:8018", "acm:239a:18"],
"msd-volume-name": "CPLAYBOOT",
"msd-firmware-name": "firmware.uf2"
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"inherits": ["nrf52840", "nrf52840-s140v6-uf2"],
"build-tags": ["clue_alpha"],
"serial-port": ["acm:239a:8072", "acm:239a:8071"],
"serial-port": ["acm:239a:8072", "acm:239a:0072", "acm:239a:0071", "acm:239a:8071"],
"msd-volume-name": "CLUEBOOT"
}
+1 -1
View File
@@ -1,5 +1,5 @@
{
"inherits": ["esp32c3"],
"build-tags": ["esp32c312f"]
"build-tags": ["esp32c312f", "esp32c3", "esp"]
}

Some files were not shown because too many files have changed in this diff Show More