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
+11 -42
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
@@ -712,9 +681,7 @@ ifneq ($(XTENSA), 0)
$(TINYGO) build -size short -o test.bin -target mch2022 examples/serial
@$(MD5SUM) test.bin
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
$(TINYGO) build -size short -o test.bin -target=esp32c3 examples/serial
@$(MD5SUM) test.bin
$(TINYGO) build -size short -o test.bin -target=m5stamp-c3 examples/serial
@$(MD5SUM) test.bin
@@ -722,6 +689,8 @@ endif
@$(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.
+10 -17
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
@@ -118,10 +117,10 @@ func (spec *TargetSpec) load(r io.Reader) error {
}
// loadFromGivenStr loads the TargetSpec from the given string that could be:
// - targets/ directory inside the compiler sources
// - a relative or absolute path to custom (project specific) target specification .json file;
// the Inherits[] could contain the files from target folder (ex. stm32f4disco)
// as well as path to custom files (ex. myAwesomeProject.json)
// - targets/ directory inside the compiler sources
// - a relative or absolute path to custom (project specific) target specification .json file;
// the Inherits[] could contain the files from target folder (ex. stm32f4disco)
// as well as path to custom files (ex. myAwesomeProject.json)
func (spec *TargetSpec) loadFromGivenStr(str string) error {
path := ""
if strings.HasSuffix(str, ".json") {
@@ -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 {
+24 -56
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
})
}
@@ -998,8 +978,7 @@ func getDefaultPort(portFlag string, usbInterfaces []string) (port string, err e
preferredPortIDs = append(preferredPortIDs, [2]uint16{uint16(vid), uint16(pid)})
}
var primaryPorts []string // ports picked from preferred USB VID/PID
var secondaryPorts []string // other ports (as a fallback)
var primaryPorts []string // ports picked from preferred USB VID/PID
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
+8 -27
View File
@@ -13,34 +13,15 @@ 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
r12 uintptr
r13 uintptr
r14 uintptr
r15 uintptr
rbx uintptr
rbp uintptr
rdi uintptr
rsi uintptr
r12 uintptr
r13 uintptr
r14 uintptr
r15 uintptr
pc 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 (
+5 -4
View File
@@ -36,9 +36,10 @@ const (
)
const (
NEOPIXEL = GPIO12
WS2812 = GPIO12
NEOPIXEL_POWER = GPIO11
NEOPIXELS = GPIO12
WS2812 = GPIO12
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
+14 -15
View File
@@ -17,8 +17,8 @@ const (
adc0_CH ADCChannel = iota
adc1_CH
adc2_CH
adc3_CH // Note: GPIO29 not broken out on pico board
adcTempSensor // Internal temperature sensor channel
adc3_CH // Note: GPIO29 not broken out on pico board
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)
}
p.Configure(PinConfig{Mode: PinAnalog})
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
}
+4 -3
View File
@@ -38,9 +38,10 @@ type SPIConfig struct {
}
var (
ErrLSBNotSupported = errors.New("SPI LSB unsupported on PL022")
ErrSPITimeout = errors.New("SPI timeout")
ErrSPIBaud = errors.New("SPI baud too low or above 66.5Mhz")
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")
)
type SPI struct {
+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:
+20 -68
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)
heapStart = uintptr(unsafe.Pointer(&heapStartSymbol))
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