mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-07-26 14:48:40 +00:00
Compare commits
27 Commits
pr3119
...
wasm-no-malloc
| Author | SHA1 | Date | |
|---|---|---|---|
| 28a083633c | |||
| 7e7814a087 | |||
| 03d1c44265 | |||
| dc0346d968 | |||
| dadae95448 | |||
| f5fc2fc072 | |||
| 4ba76a5df9 | |||
| ea1e08f53f | |||
| bba0dc9575 | |||
| 617c7586fe | |||
| 7366d5e185 | |||
| 96e3ecd949 | |||
| 8bbfb1ee68 | |||
| 07cdcc61f7 | |||
| 4ca9b34133 | |||
| d5e4b16911 | |||
| fd05254683 | |||
| c579e7e509 | |||
| d463528a72 | |||
| 49b0086f8f | |||
| d7814ff50b | |||
| 02160aa8d8 | |||
| c199dd03c7 | |||
| 472aecf07a | |||
| 09350e5719 | |||
| 623dd6a815 | |||
| e09bd5abb3 |
@@ -16,10 +16,6 @@ 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: |
|
||||
@@ -35,8 +31,13 @@ jobs:
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.18.1'
|
||||
cache: true
|
||||
- name: Cache LLVM source
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
id: cache-llvm-source
|
||||
with:
|
||||
key: llvm-source-14-macos-v1
|
||||
@@ -50,7 +51,7 @@ jobs:
|
||||
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
||||
run: make llvm-source
|
||||
- name: Cache LLVM build
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
id: cache-llvm-build
|
||||
with:
|
||||
key: llvm-build-14-macos-v1
|
||||
@@ -68,7 +69,7 @@ jobs:
|
||||
make llvm-build
|
||||
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
|
||||
- name: Cache wasi-libc sysroot
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
id: cache-wasi-libc
|
||||
with:
|
||||
key: wasi-libc-sysroot-v4
|
||||
@@ -104,23 +105,17 @@ 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: Cache Go
|
||||
uses: actions/cache@v2
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
key: go-cache-macos-homebrew-v1-${{ hashFiles('go.mod') }}
|
||||
path: |
|
||||
~/Library/Caches/go-build
|
||||
~/go/pkg/mod
|
||||
go-version: '1.18'
|
||||
cache: true
|
||||
- name: Build TinyGo
|
||||
run: go install
|
||||
- name: Check binary
|
||||
|
||||
+26
-48
@@ -18,14 +18,13 @@ jobs:
|
||||
# statically linked binary.
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: alpine:3.16
|
||||
image: golang:1.18-alpine
|
||||
steps:
|
||||
- name: Install apk dependencies
|
||||
# tar: needed for actions/cache@v2
|
||||
# tar: needed for actions/cache@v3
|
||||
# git+openssh: needed for checkout (I think?)
|
||||
# gcompat: needed for go binary
|
||||
# ruby: needed to install fpm
|
||||
run: apk add tar git openssh gcompat make g++ ruby
|
||||
run: apk add tar git openssh 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"
|
||||
@@ -33,19 +32,15 @@ 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@v2
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
key: go-cache-linux-alpine-v1-${{ hashFiles('go.mod') }}
|
||||
path: |
|
||||
~/.cache/go-build
|
||||
~/go/pkg/mod
|
||||
- name: Cache LLVM source
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
id: cache-llvm-source
|
||||
with:
|
||||
key: llvm-source-14-linux-alpine-v1
|
||||
@@ -59,7 +54,7 @@ jobs:
|
||||
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
||||
run: make llvm-source
|
||||
- name: Cache LLVM build
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
id: cache-llvm-build
|
||||
with:
|
||||
key: llvm-build-14-linux-alpine-v1
|
||||
@@ -77,7 +72,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@v2
|
||||
uses: actions/cache@v3
|
||||
id: cache-binaryen
|
||||
with:
|
||||
key: binaryen-linux-alpine-v1
|
||||
@@ -88,7 +83,7 @@ jobs:
|
||||
apk add cmake samurai python3
|
||||
make binaryen STATIC=1
|
||||
- name: Cache wasi-libc
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
id: cache-wasi-libc
|
||||
with:
|
||||
key: wasi-libc-sysroot-linux-alpine-v1
|
||||
@@ -121,9 +116,10 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.18.1'
|
||||
cache: true
|
||||
- name: Install wasmtime
|
||||
run: |
|
||||
curl https://wasmtime.dev/install.sh -sSf | bash
|
||||
@@ -173,9 +169,10 @@ jobs:
|
||||
simavr \
|
||||
ninja-build
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.18.1'
|
||||
cache: true
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
@@ -184,15 +181,8 @@ 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@v2
|
||||
uses: actions/cache@v3
|
||||
id: cache-llvm-source
|
||||
with:
|
||||
key: llvm-source-14-linux-asserts-v2
|
||||
@@ -206,7 +196,7 @@ jobs:
|
||||
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
||||
run: make llvm-source
|
||||
- name: Cache LLVM build
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
id: cache-llvm-build
|
||||
with:
|
||||
key: llvm-build-14-linux-asserts-v1
|
||||
@@ -222,7 +212,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@v2
|
||||
uses: actions/cache@v3
|
||||
id: cache-binaryen
|
||||
with:
|
||||
key: binaryen-linux-asserts-v1
|
||||
@@ -231,7 +221,7 @@ jobs:
|
||||
if: steps.cache-binaryen.outputs.cache-hit != 'true'
|
||||
run: make binaryen
|
||||
- name: Cache wasi-libc
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
id: cache-wasi-libc
|
||||
with:
|
||||
key: wasi-libc-sysroot-linux-asserts-v5
|
||||
@@ -279,18 +269,12 @@ jobs:
|
||||
g++-arm-linux-gnueabihf \
|
||||
libc6-dev-armhf-cross
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
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
|
||||
cache: true
|
||||
- name: Cache LLVM source
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
id: cache-llvm-source
|
||||
with:
|
||||
key: llvm-source-14-linux-v2
|
||||
@@ -304,7 +288,7 @@ jobs:
|
||||
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
||||
run: make llvm-source
|
||||
- name: Cache LLVM build
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
id: cache-llvm-build
|
||||
with:
|
||||
key: llvm-build-14-linux-arm-v1
|
||||
@@ -322,7 +306,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@v2
|
||||
uses: actions/cache@v3
|
||||
id: cache-binaryen
|
||||
with:
|
||||
key: binaryen-linux-arm-v1
|
||||
@@ -385,18 +369,12 @@ jobs:
|
||||
libc6-dev-arm64-cross \
|
||||
ninja-build
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
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
|
||||
cache: true
|
||||
- name: Cache LLVM source
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
id: cache-llvm-source
|
||||
with:
|
||||
key: llvm-source-14-linux-v1
|
||||
@@ -410,7 +388,7 @@ jobs:
|
||||
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
||||
run: make llvm-source
|
||||
- name: Cache LLVM build
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
id: cache-llvm-build
|
||||
with:
|
||||
key: llvm-build-14-linux-arm64-v1
|
||||
@@ -426,7 +404,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@v2
|
||||
uses: actions/cache@v3
|
||||
id: cache-binaryen
|
||||
with:
|
||||
key: binaryen-linux-arm64-v1
|
||||
|
||||
@@ -15,10 +15,6 @@ 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'
|
||||
@@ -30,15 +26,13 @@ jobs:
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Cache Go
|
||||
uses: actions/cache@v2
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
key: go-cache-windows-v1-${{ hashFiles('go.mod') }}
|
||||
path: |
|
||||
~/AppData/Local/go-build
|
||||
~/go/pkg/mod
|
||||
go-version: '1.18.1'
|
||||
cache: true
|
||||
- name: Cache LLVM source
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
id: cache-llvm-source
|
||||
with:
|
||||
key: llvm-source-14-windows-v2
|
||||
@@ -52,7 +46,7 @@ jobs:
|
||||
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
||||
run: make llvm-source
|
||||
- name: Cache LLVM build
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
id: cache-llvm-build
|
||||
with:
|
||||
key: llvm-build-14-windows-v2
|
||||
@@ -69,7 +63,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@v2
|
||||
uses: actions/cache@v3
|
||||
id: cache-wasi-libc
|
||||
with:
|
||||
key: wasi-libc-sysroot-v4
|
||||
|
||||
@@ -326,11 +326,15 @@ 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/fs requires os.ReadDir, which is not yet supported on windows or wasi
|
||||
# io/ioutil requires os.ReadDir, which is not yet supported on windows or wasi
|
||||
# strconv requires recover() which is not yet supported on wasi
|
||||
# text/template/parse requires recover(), which is not yet supported on wasi
|
||||
# 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 := \
|
||||
@@ -349,7 +353,12 @@ TEST_PACKAGES_LINUX := \
|
||||
TEST_PACKAGES_DARWIN := $(TEST_PACKAGES_LINUX)
|
||||
|
||||
TEST_PACKAGES_WINDOWS := \
|
||||
compress/lzw
|
||||
compress/flate \
|
||||
compress/lzw \
|
||||
crypto/hmac \
|
||||
strconv \
|
||||
text/template/parse \
|
||||
$(nil)
|
||||
|
||||
# Report platforms on which each standard library package is known to pass tests
|
||||
jointmp := $(shell echo /tmp/join.$$$$)
|
||||
@@ -386,9 +395,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)
|
||||
$(TINYGO) test -target wasi $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW) ./tests/runtime_wasi
|
||||
tinygo-test-wasi-fast:
|
||||
$(TINYGO) test -target wasi $(TEST_PACKAGES_FAST)
|
||||
$(TINYGO) test -target wasi $(TEST_PACKAGES_FAST) ./tests/runtime_wasi
|
||||
tinygo-bench-wasi:
|
||||
$(TINYGO) test -target wasi -bench . $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW)
|
||||
tinygo-bench-wasi-fast:
|
||||
@@ -410,6 +419,7 @@ 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
|
||||
@@ -519,6 +529,8 @@ 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
|
||||
@@ -585,6 +597,8 @@ endif
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=feather-rp2040 examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=qtpy-rp2040 examples/echo
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=macropad-rp2040 examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=badger2040 examples/blinky1
|
||||
@@ -679,7 +693,9 @@ 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
|
||||
$(TINYGO) build -size short -o test.bin -target=esp32c3 examples/serial
|
||||
@$(MD5SUM) test.bin
|
||||
$(TINYGO) build -size short -o test.bin -target=esp32c3-12f examples/serial
|
||||
@$(MD5SUM) test.bin
|
||||
$(TINYGO) build -size short -o test.bin -target=m5stamp-c3 examples/serial
|
||||
@$(MD5SUM) test.bin
|
||||
@@ -687,8 +703,6 @@ 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)
|
||||
|
||||
@@ -66,6 +66,7 @@ The following 91 microcontroller boards are currently supported:
|
||||
* [Adafruit PyGamer](https://www.adafruit.com/product/4242)
|
||||
* [Adafruit PyPortal](https://www.adafruit.com/product/4116)
|
||||
* [Adafruit QT Py](https://www.adafruit.com/product/4600)
|
||||
* [Adafruit QT Py RP2040](https://www.adafruit.com/product/4900)
|
||||
* [Adafruit Trinket M0](https://www.adafruit.com/product/3500)
|
||||
* [Adafruit Trinkey QT2040](https://adafruit.com/product/5056)
|
||||
* [Arduino Mega 1280](https://www.arduino.cc/en/Main/arduinoBoardMega/)
|
||||
@@ -124,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)
|
||||
* [SiFIve HiFive1 Rev B](https://www.sifive.com/boards/hifive1-rev-b)
|
||||
* [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)
|
||||
|
||||
@@ -142,6 +142,7 @@ var validLinkerFlags = []*regexp.Regexp{
|
||||
re(`-L([^@\-].*)`),
|
||||
re(`-O`),
|
||||
re(`-O([^@\-].*)`),
|
||||
re(`--export=(.+)`), // for wasm-ld
|
||||
re(`-f(no-)?(pic|PIC|pie|PIE)`),
|
||||
re(`-f(no-)?openmp(-simd)?`),
|
||||
re(`-fsanitize=([^@\-].*)`),
|
||||
|
||||
@@ -457,7 +457,14 @@ func (c *Config) OpenOCDConfiguration() (args []string, err error) {
|
||||
args = append(args, "-c", cmd)
|
||||
}
|
||||
if c.Target.OpenOCDTransport != "" {
|
||||
args = append(args, "-c", "transport select "+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, "-f", "target/"+c.Target.OpenOCDTarget+".cfg")
|
||||
return args, nil
|
||||
|
||||
+17
-10
@@ -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) {
|
||||
func (spec *TargetSpec) overrideProperties(child *TargetSpec) error {
|
||||
specType := reflect.TypeOf(spec).Elem()
|
||||
specValue := reflect.ValueOf(spec).Elem()
|
||||
childValue := reflect.ValueOf(child).Elem()
|
||||
@@ -95,14 +95,15 @@ func (spec *TargetSpec) overrideProperties(child *TargetSpec) {
|
||||
for j := i + 1; j < dst.Len(); j++ {
|
||||
w := dst.Index(j).String()
|
||||
if v == w {
|
||||
panic("duplicate value '" + v + "' in field : " + field.Name)
|
||||
return fmt.Errorf("duplicate value '%s' in field %s", v, field.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
panic("unknown field type : " + kind.String())
|
||||
return fmt.Errorf("unknown field type: %s", kind)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// load reads a target specification from the JSON in the given io.Reader. It
|
||||
@@ -117,10 +118,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") {
|
||||
@@ -150,11 +151,17 @@ func (spec *TargetSpec) resolveInherits() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newSpec.overrideProperties(subtarget)
|
||||
err = newSpec.overrideProperties(subtarget)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// When all properties are loaded, make sure they are properly inherited.
|
||||
newSpec.overrideProperties(spec)
|
||||
err := newSpec.overrideProperties(spec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*spec = *newSpec
|
||||
|
||||
return nil
|
||||
@@ -221,7 +228,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, err
|
||||
return nil, fmt.Errorf("%s : %w", options.Target, err)
|
||||
}
|
||||
|
||||
if spec.Scheduler == "asyncify" {
|
||||
|
||||
@@ -1059,11 +1059,12 @@ func (b *builder) createFunctionStart(intrinsic bool) {
|
||||
if b.info.section != "" {
|
||||
b.llvmFn.SetSection(b.info.section)
|
||||
}
|
||||
if b.info.exported && strings.HasPrefix(b.Triple, "wasm") {
|
||||
if b.info.exported && b.info.module != "" && strings.HasPrefix(b.Triple, "wasm") {
|
||||
// Set the exported name. This is necessary for WebAssembly because
|
||||
// otherwise the function is not exported.
|
||||
functionAttr := b.ctx.CreateStringAttribute("wasm-export-name", b.info.linkName)
|
||||
b.llvmFn.AddFunctionAttr(functionAttr)
|
||||
b.llvmFn.AddFunctionAttr(b.ctx.CreateStringAttribute("wasm-export-name", b.info.linkName))
|
||||
// Set the export module.
|
||||
b.llvmFn.AddFunctionAttr(b.ctx.CreateStringAttribute("wasm-export-module", b.info.module))
|
||||
}
|
||||
|
||||
// Some functions have a pragma controlling the inlining level.
|
||||
|
||||
+23
-31
@@ -163,18 +163,20 @@ 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 {
|
||||
// Set the wasm-import-module attribute if the function's module is set.
|
||||
if info.module != "" {
|
||||
|
||||
if c.archFamily() == "wasm32" {
|
||||
// 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)
|
||||
// attributes.
|
||||
module := info.module
|
||||
if module == "" {
|
||||
module = "env"
|
||||
}
|
||||
llvmFn.AddFunctionAttr(c.ctx.CreateStringAttribute("wasm-import-module", module))
|
||||
|
||||
name := info.importName
|
||||
if name == "" {
|
||||
name = info.linkName
|
||||
}
|
||||
llvmFn.AddFunctionAttr(c.ctx.CreateStringAttribute("wasm-import-name", name))
|
||||
}
|
||||
nocaptureKind := llvm.AttributeKindID("nocapture")
|
||||
nocapture := c.ctx.CreateEnumAttribute(nocaptureKind, 0)
|
||||
@@ -208,8 +210,9 @@ func (c *compilerContext) getFunction(fn *ssa.Function) llvm.Value {
|
||||
// exported.
|
||||
func (c *compilerContext) getFunctionInfo(f *ssa.Function) functionInfo {
|
||||
info := functionInfo{
|
||||
// Pick the default linkName.
|
||||
linkName: f.RelString(nil),
|
||||
module: "env",
|
||||
importName: f.Name(),
|
||||
linkName: f.RelString(nil), // pick the default linkName
|
||||
}
|
||||
// Check for //go: pragmas, which may change the link name (among others).
|
||||
info.parsePragmas(f)
|
||||
@@ -223,10 +226,6 @@ func (info *functionInfo) parsePragmas(f *ssa.Function) {
|
||||
return
|
||||
}
|
||||
if decl, ok := f.Syntax().(*ast.FuncDecl); ok && decl.Doc != nil {
|
||||
|
||||
// Our importName for a wasm module (if we are compiling to wasm), or llvm link name
|
||||
var importName string
|
||||
|
||||
for _, comment := range decl.Doc.List {
|
||||
text := comment.Text
|
||||
if strings.HasPrefix(text, "//export ") {
|
||||
@@ -244,7 +243,8 @@ func (info *functionInfo) parsePragmas(f *ssa.Function) {
|
||||
continue
|
||||
}
|
||||
|
||||
importName = parts[1]
|
||||
info.importName = parts[1]
|
||||
info.linkName = parts[1]
|
||||
info.exported = true
|
||||
case "//go:interrupt":
|
||||
if hasUnsafeImport(f.Pkg.Pkg) {
|
||||
@@ -252,10 +252,13 @@ func (info *functionInfo) parsePragmas(f *ssa.Function) {
|
||||
}
|
||||
case "//go:wasm-module":
|
||||
// Alternative comment for setting the import module.
|
||||
if len(parts) != 2 {
|
||||
continue
|
||||
if len(parts) == 1 {
|
||||
// Function must not be exported outside of the WebAssembly
|
||||
// module (but only be made available for linking).
|
||||
info.module = ""
|
||||
} else if len(parts) == 2 {
|
||||
info.module = parts[1]
|
||||
}
|
||||
info.module = parts[1]
|
||||
case "//go:inline":
|
||||
info.inline = inlineHint
|
||||
case "//go:noinline":
|
||||
@@ -295,17 +298,6 @@ func (info *functionInfo) parsePragmas(f *ssa.Function) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set the importName for our exported function if we have one
|
||||
if importName != "" {
|
||||
if info.module == "" {
|
||||
info.linkName = importName
|
||||
} else {
|
||||
// WebAssembly import
|
||||
info.importName = importName
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Vendored
+2
-2
@@ -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" }
|
||||
attributes #2 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" "wasm-export-module"="env" "wasm-export-name"="extern_func" "wasm-import-module"="env" "wasm-import-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" }
|
||||
attributes #5 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" "wasm-export-module"="env" "wasm-export-name"="exportedFunctionInSection" "wasm-import-module"="env" "wasm-import-name"="exportedFunctionInSection" }
|
||||
|
||||
@@ -243,17 +243,36 @@ func Test(pkgName string, stdout, stderr io.Writer, options *compileopts.Options
|
||||
// Tests are always run in the package directory.
|
||||
cmd.Dir = result.MainDir
|
||||
|
||||
// Wasmtime needs a few extra flags to work.
|
||||
// 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.
|
||||
if config.EmulatorName() == "wasmtime" {
|
||||
// Add directories to the module root, but skip the current working
|
||||
// directory which is already added by buildAndRun.
|
||||
// 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=../../..
|
||||
dirs := dirsToModuleRoot(result.MainDir, result.ModuleRoot)
|
||||
var args []string
|
||||
for _, d := range dirs[1:] {
|
||||
args = append(args, "--dir="+d)
|
||||
}
|
||||
|
||||
// create a new temp directory just for this run, announce it to os.TempDir() via TMPDIR
|
||||
// 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.
|
||||
tmpdir, err := os.MkdirTemp("", "tinygotmp")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create temporary directory: %w", err)
|
||||
@@ -262,7 +281,8 @@ 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)
|
||||
|
||||
// Insert new argments at the front of the command line argments.
|
||||
// The below re-organizes the arguments so that the current
|
||||
// directory is added last.
|
||||
args = append(args, cmd.Args[1:]...)
|
||||
cmd.Args = append(cmd.Args[:1:1], args...)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//go:build stm32 || (sam && atsamd51) || (sam && atsame5x)
|
||||
// +build stm32 sam,atsamd51 sam,atsame5x
|
||||
//go:build nrf52840 || stm32 || (sam && atsamd51) || (sam && atsame5x) || rp2040
|
||||
// +build nrf52840 stm32 sam,atsamd51 sam,atsame5x rp2040
|
||||
|
||||
package rand
|
||||
|
||||
|
||||
@@ -21,12 +21,14 @@ $ 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.
|
||||
|
||||
This examples folder contains two examples that can be built using `make`:
|
||||
|
||||
```bash
|
||||
$ make export
|
||||
```
|
||||
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.
|
||||
|
||||
Let's say you chose [main](main), you'd build it like so:
|
||||
```bash
|
||||
$ make main
|
||||
```
|
||||
@@ -42,12 +44,8 @@ Serving ./html on http://localhost:8080
|
||||
|
||||
Use your web browser to visit http://localhost:8080.
|
||||
|
||||
* 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.
|
||||
* Tip: Open the browser development tools (e.g. Right-click, Inspect in
|
||||
FireFox) to see console output.
|
||||
|
||||
## How it works
|
||||
|
||||
|
||||
@@ -8,10 +8,12 @@ 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 {
|
||||
|
||||
@@ -2,12 +2,16 @@
|
||||
|
||||
.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
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
// 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
|
||||
@@ -17,8 +20,9 @@ tinygo_startTask:
|
||||
// Branch to the "goroutine start" function.
|
||||
callq *%r12
|
||||
|
||||
// After return, exit this goroutine. This is a tail call.
|
||||
jmp tinygo_pause
|
||||
// After return, exit this goroutine.
|
||||
// This has to be a call, not a jump, to keep the stack correctly aligned.
|
||||
callq tinygo_pause
|
||||
|
||||
.global tinygo_swapTask
|
||||
.section .text.tinygo_swapTask,"ax"
|
||||
@@ -35,6 +39,17 @@ 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.
|
||||
@@ -45,6 +60,17 @@ tinygo_swapTask:
|
||||
|
||||
// Load saved register from the new stack.
|
||||
popq %rbx
|
||||
movaps 0(%rsp), %xmm15
|
||||
movaps 16(%rsp), %xmm14
|
||||
movaps 32(%rsp), %xmm13
|
||||
movaps 48(%rsp), %xmm12
|
||||
movaps 64(%rsp), %xmm11
|
||||
movaps 80(%rsp), %xmm10
|
||||
movaps 96(%rsp), %xmm9
|
||||
movaps 112(%rsp), %xmm8
|
||||
movaps 128(%rsp), %xmm7
|
||||
movaps 144(%rsp), %xmm6
|
||||
add $160, %rsp
|
||||
popq %rbp
|
||||
popq %rdi
|
||||
popq %rsi
|
||||
|
||||
@@ -13,15 +13,34 @@ 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 {
|
||||
rbx uintptr
|
||||
rbp uintptr
|
||||
rdi uintptr
|
||||
rsi uintptr
|
||||
r12 uintptr
|
||||
r13 uintptr
|
||||
r14 uintptr
|
||||
r15 uintptr
|
||||
// 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
|
||||
|
||||
pc uintptr
|
||||
}
|
||||
|
||||
@@ -12,9 +12,9 @@ const (
|
||||
|
||||
const (
|
||||
PB0 = portB + 0
|
||||
PB1 = portB + 1
|
||||
PB2 = portB + 2
|
||||
PB3 = portB + 3
|
||||
PB1 = portB + 1 // peripherals: Timer1 channel A
|
||||
PB2 = portB + 2 // peripherals: Timer1 channel B
|
||||
PB3 = portB + 3 // peripherals: Timer2 channel A
|
||||
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
|
||||
PD3 = portD + 3 // peripherals: Timer2 channel B
|
||||
PD4 = portD + 4
|
||||
PD5 = portD + 5
|
||||
PD6 = portD + 6
|
||||
PD5 = portD + 5 // peripherals: Timer0 channel B
|
||||
PD6 = portD + 6 // peripherals: Timer0 channel A
|
||||
PD7 = portD + 7
|
||||
)
|
||||
|
||||
@@ -10,38 +10,38 @@ func CPUFrequency() uint32 {
|
||||
|
||||
// Hardware pins
|
||||
const (
|
||||
PA00 Pin = 0
|
||||
PA01 Pin = 1
|
||||
PA00 Pin = 0 // peripherals: TCC2 channel 0
|
||||
PA01 Pin = 1 // peripherals: TCC2 channel 1
|
||||
PA02 Pin = 2
|
||||
PA03 Pin = 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
|
||||
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
|
||||
PA26 Pin = 26
|
||||
PA27 Pin = 27
|
||||
PA28 Pin = 28
|
||||
PA29 Pin = 29
|
||||
PA30 Pin = 30
|
||||
PA31 Pin = 31
|
||||
PA30 Pin = 30 // peripherals: TCC1 channel 0
|
||||
PA31 Pin = 31 // peripherals: TCC1 channel 1
|
||||
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
|
||||
PB11 Pin = 43
|
||||
PB12 Pin = 44
|
||||
PB13 Pin = 45
|
||||
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
|
||||
PB14 Pin = 46
|
||||
PB15 Pin = 47
|
||||
PB16 Pin = 48
|
||||
PB17 Pin = 49
|
||||
PB16 Pin = 48 // peripherals: TCC0 channel 0
|
||||
PB17 Pin = 49 // peripherals: TCC0 channel 1
|
||||
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
|
||||
PB31 Pin = 63
|
||||
PB30 Pin = 62 // peripherals: TCC0 channel 0, TCC1 channel 2
|
||||
PB31 Pin = 63 // peripherals: TCC0 channel 1, TCC1 channel 3
|
||||
)
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
//go:build qtpy_rp2040
|
||||
// +build qtpy_rp2040
|
||||
|
||||
package machine
|
||||
|
||||
import (
|
||||
"device/rp"
|
||||
"runtime/interrupt"
|
||||
)
|
||||
|
||||
// Onboard crystal oscillator frequency, in MHz.
|
||||
const xoscFreq = 12 // MHz
|
||||
|
||||
// GPIO Pins
|
||||
const (
|
||||
SDA = GPIO24
|
||||
SCL = GPIO25
|
||||
TX = GPIO20
|
||||
MO = GPIO3
|
||||
MOSI = GPIO3
|
||||
MI = GPIO4
|
||||
MISO = GPIO4
|
||||
SCK = GPIO6
|
||||
RX = GPIO5
|
||||
|
||||
QT_SCL1 = GPIO23
|
||||
QT_SDA1 = GPIO22
|
||||
)
|
||||
|
||||
// Analog pins
|
||||
const (
|
||||
A0 = GPIO29
|
||||
A1 = GPIO28
|
||||
A2 = GPIO27
|
||||
A3 = GPIO26
|
||||
)
|
||||
|
||||
const (
|
||||
NEOPIXEL = GPIO12
|
||||
WS2812 = GPIO12
|
||||
NEOPIXEL_POWER = GPIO11
|
||||
)
|
||||
|
||||
// I2C Pins.
|
||||
const (
|
||||
I2C0_SDA_PIN = GPIO24
|
||||
I2C0_SCL_PIN = GPIO25
|
||||
|
||||
I2C1_SDA_PIN = GPIO26
|
||||
I2C1_SCL_PIN = GPIO27
|
||||
|
||||
I2C1_QT_SDA_PIN = GPIO22
|
||||
I2C1_QT_SCL_PIN = GPIO23
|
||||
|
||||
SDA_PIN = GPIO24
|
||||
SCL_PIN = GPIO25
|
||||
)
|
||||
|
||||
// SPI default pins
|
||||
const (
|
||||
// Default Serial Clock Bus 0 for SPI communications
|
||||
SPI0_SCK_PIN = GPIO6
|
||||
// Default Serial Out Bus 0 for SPI communications
|
||||
SPI0_SDO_PIN = GPIO3 // Tx
|
||||
// Default Serial In Bus 0 for SPI communications
|
||||
SPI0_SDI_PIN = GPIO4 // Rx
|
||||
SPI0_CS = GPIO5
|
||||
|
||||
// Default Serial Clock Bus 1 for SPI communications
|
||||
SPI1_SCK_PIN = GPIO26
|
||||
// Default Serial Out Bus 1 for SPI communications
|
||||
SPI1_SDO_PIN = GPIO27 // Tx
|
||||
// Default Serial In Bus 1 for SPI communications
|
||||
SPI1_SDI_PIN = GPIO24 // Rx
|
||||
SPI1_CS = GPIO25
|
||||
)
|
||||
|
||||
// UART pins
|
||||
const (
|
||||
UART0_TX_PIN = GPIO28
|
||||
UART0_RX_PIN = GPIO29
|
||||
UART1_TX_PIN = GPIO20
|
||||
UART1_RX_PIN = GPIO5
|
||||
UART_TX_PIN = UART0_TX_PIN
|
||||
UART_RX_PIN = UART0_RX_PIN
|
||||
)
|
||||
|
||||
// UART on the RP2040
|
||||
var (
|
||||
UART0 = &_UART0
|
||||
_UART0 = UART{
|
||||
Buffer: NewRingBuffer(),
|
||||
Bus: rp.UART0,
|
||||
}
|
||||
|
||||
UART1 = &_UART1
|
||||
_UART1 = UART{
|
||||
Buffer: NewRingBuffer(),
|
||||
Bus: rp.UART1,
|
||||
}
|
||||
)
|
||||
|
||||
var DefaultUART = UART0
|
||||
|
||||
func init() {
|
||||
UART0.Interrupt = interrupt.New(rp.IRQ_UART0_IRQ, _UART0.handleInterrupt)
|
||||
UART1.Interrupt = interrupt.New(rp.IRQ_UART1_IRQ, _UART1.handleInterrupt)
|
||||
}
|
||||
|
||||
// USB identifiers
|
||||
const (
|
||||
usb_STRING_PRODUCT = "QT Py RP2040"
|
||||
usb_STRING_MANUFACTURER = "Adafruit"
|
||||
)
|
||||
|
||||
var (
|
||||
usb_VID uint16 = 0x239A
|
||||
usb_PID uint16 = 0x80F7
|
||||
)
|
||||
@@ -38,10 +38,10 @@ const (
|
||||
PB1 = portB + 1
|
||||
PB2 = portB + 2
|
||||
PB3 = portB + 3
|
||||
PB4 = portB + 4
|
||||
PB5 = portB + 5
|
||||
PB6 = portB + 6
|
||||
PB7 = portB + 7
|
||||
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
|
||||
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
|
||||
PE4 = portE + 4
|
||||
PE5 = portE + 5
|
||||
PE3 = portE + 3 // peripherals: Timer3 channel A
|
||||
PE4 = portE + 4 // peripherals: Timer3 channel B
|
||||
PE5 = portE + 5 // peripherals: Timer3 channel C
|
||||
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
|
||||
PG5 = portG + 5 // peripherals: Timer0 channel B
|
||||
PH0 = portH + 0
|
||||
PH1 = portH + 1
|
||||
PH3 = portH + 3
|
||||
PH4 = portH + 4
|
||||
PH5 = portH + 5
|
||||
PH6 = portH + 6
|
||||
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
|
||||
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
|
||||
PL4 = portL + 4
|
||||
PL5 = portL + 5
|
||||
PL3 = portL + 3 // peripherals: Timer5 channel A
|
||||
PL4 = portL + 4 // peripherals: Timer5 channel B
|
||||
PL5 = portL + 5 // peripherals: Timer5 channel C
|
||||
PL6 = portL + 6
|
||||
PL7 = portL + 7
|
||||
)
|
||||
|
||||
@@ -78,86 +78,86 @@ const (
|
||||
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
|
||||
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
|
||||
PA26 Pin = 26
|
||||
PA27 Pin = 27
|
||||
PA28 Pin = 28
|
||||
PA29 Pin = 29
|
||||
PA30 Pin = 30
|
||||
PA31 Pin = 31
|
||||
PA30 Pin = 30 // peripherals: TCC2 channel 0
|
||||
PA31 Pin = 31 // peripherals: TCC2 channel 1
|
||||
PB00 Pin = 32
|
||||
PB01 Pin = 33
|
||||
PB02 Pin = 34
|
||||
PB03 Pin = 35
|
||||
PB02 Pin = 34 // peripherals: TCC2 channel 2
|
||||
PB03 Pin = 35 // peripherals: TCC2 channel 3
|
||||
PB04 Pin = 36
|
||||
PB05 Pin = 37
|
||||
PB06 Pin = 38
|
||||
PB07 Pin = 39
|
||||
PB08 Pin = 40
|
||||
PB09 Pin = 41
|
||||
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
|
||||
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
|
||||
PB22 Pin = 54
|
||||
PB23 Pin = 55
|
||||
PB24 Pin = 56
|
||||
PB25 Pin = 57
|
||||
PB26 Pin = 58
|
||||
PB27 Pin = 59
|
||||
PB28 Pin = 60
|
||||
PB29 Pin = 61
|
||||
PB30 Pin = 62
|
||||
PB31 Pin = 63
|
||||
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
|
||||
PC00 Pin = 64
|
||||
PC01 Pin = 65
|
||||
PC02 Pin = 66
|
||||
PC03 Pin = 67
|
||||
PC04 Pin = 68
|
||||
PC05 Pin = 69
|
||||
PC04 Pin = 68 // peripherals: TCC0 channel 0
|
||||
PC05 Pin = 69 // peripherals: TCC0 channel 1
|
||||
PC06 Pin = 70
|
||||
PC07 Pin = 71
|
||||
PC08 Pin = 72
|
||||
PC09 Pin = 73
|
||||
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
|
||||
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
|
||||
PC24 Pin = 88
|
||||
PC25 Pin = 89
|
||||
PC26 Pin = 90
|
||||
@@ -174,20 +174,20 @@ const (
|
||||
PD05 Pin = 101
|
||||
PD06 Pin = 102
|
||||
PD07 Pin = 103
|
||||
PD08 Pin = 104
|
||||
PD09 Pin = 105
|
||||
PD10 Pin = 106
|
||||
PD11 Pin = 107
|
||||
PD12 Pin = 108
|
||||
PD13 Pin = 109
|
||||
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
|
||||
PD14 Pin = 110
|
||||
PD15 Pin = 111
|
||||
PD16 Pin = 112
|
||||
PD17 Pin = 113
|
||||
PD18 Pin = 114
|
||||
PD19 Pin = 115
|
||||
PD20 Pin = 116
|
||||
PD21 Pin = 117
|
||||
PD20 Pin = 116 // peripherals: TCC1 channel 0
|
||||
PD21 Pin = 117 // peripherals: TCC1 channel 1
|
||||
PD22 Pin = 118
|
||||
PD23 Pin = 119
|
||||
PD24 Pin = 120
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
//go:build nrf52840
|
||||
// +build nrf52840
|
||||
|
||||
package machine
|
||||
|
||||
import (
|
||||
"device/nrf"
|
||||
)
|
||||
|
||||
// Implementation based on Nordic Semiconductor's nRF52840 documentation version 1.7 found here:
|
||||
// https://infocenter.nordicsemi.com/pdf/nRF52840_PS_v1.7.pdf
|
||||
|
||||
// SetRNGBiasCorrection configures the RNG peripheral's bias correction mechanism. Note that when
|
||||
// bias correction is enabled, the peripheral is slower to produce random values.
|
||||
func SetRNGBiasCorrection(enabled bool) {
|
||||
var val uint32
|
||||
if enabled {
|
||||
val = nrf.RNG_CONFIG_DERCEN_Enabled
|
||||
}
|
||||
nrf.RNG.SetCONFIG_DERCEN(val)
|
||||
}
|
||||
|
||||
// RNGBiasCorrectionEnabled determines whether the RNG peripheral's bias correction mechanism is
|
||||
// enabled or not.
|
||||
func RNGBiasCorrectionEnabled() bool {
|
||||
return nrf.RNG.GetCONFIG_DERCEN() == nrf.RNG_CONFIG_DERCEN_Enabled
|
||||
}
|
||||
|
||||
// StartRNG starts the RNG peripheral core. This is automatically called by GetRNG, but can be
|
||||
// manually called for interacting with the RNG peripheral directly.
|
||||
func StartRNG() {
|
||||
nrf.RNG.SetTASKS_START(nrf.RNG_TASKS_START_TASKS_START_Trigger)
|
||||
}
|
||||
|
||||
// StopRNG stops the RNG peripheral core. This is not called automatically. It may make sense to
|
||||
// manually disable RNG peripheral for power conservation.
|
||||
func StopRNG() {
|
||||
nrf.RNG.SetTASKS_STOP(nrf.RNG_TASKS_STOP_TASKS_STOP_Trigger)
|
||||
}
|
||||
|
||||
// GetRNG returns 32 bits of non-deterministic random data based on internal thermal noise.
|
||||
// According to Nordic's documentation, the random output is suitable for cryptographic purposes.
|
||||
func GetRNG() (ret uint32, err error) {
|
||||
// There's no apparent way to check the status of the RNG peripheral's task, so simply start it
|
||||
// to avoid deadlocking while waiting for output.
|
||||
StartRNG()
|
||||
|
||||
// The RNG returns one byte at a time, so stack up four bytes into a single uint32 for return.
|
||||
for i := 0; i < 4; i++ {
|
||||
// Wait for data to be ready.
|
||||
for nrf.RNG.GetEVENTS_VALRDY() == nrf.RNG_EVENTS_VALRDY_EVENTS_VALRDY_NotGenerated {
|
||||
}
|
||||
// Append random byte to output.
|
||||
ret = (ret << 8) ^ nrf.RNG.GetVALUE()
|
||||
// Unset the EVENTS_VALRDY register to avoid reading the same random output twice.
|
||||
nrf.RNG.SetEVENTS_VALRDY(nrf.RNG_EVENTS_VALRDY_EVENTS_VALRDY_NotGenerated)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
@@ -11,36 +11,36 @@ const deviceName = rp.Device
|
||||
|
||||
const (
|
||||
// GPIO pins
|
||||
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
|
||||
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
|
||||
|
||||
// Analog pins
|
||||
ADC0 Pin = GPIO26
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
//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.
|
||||
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
|
||||
}
|
||||
@@ -61,31 +61,58 @@ func growHeap() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// 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.
|
||||
// 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)
|
||||
|
||||
//export malloc
|
||||
//go:wasm-module
|
||||
func libc_malloc(size uintptr) unsafe.Pointer {
|
||||
return alloc(size, nil)
|
||||
buf := make([]byte, size)
|
||||
ptr := unsafe.Pointer(&buf[0])
|
||||
allocs[uintptr(ptr)] = buf
|
||||
return ptr
|
||||
}
|
||||
|
||||
//export free
|
||||
//go:wasm-module
|
||||
func libc_free(ptr unsafe.Pointer) {
|
||||
free(ptr)
|
||||
if ptr == nil {
|
||||
return
|
||||
}
|
||||
if _, ok := allocs[uintptr(ptr)]; ok {
|
||||
delete(allocs, uintptr(ptr))
|
||||
} else {
|
||||
panic("free: invalid pointer")
|
||||
}
|
||||
}
|
||||
|
||||
//export calloc
|
||||
//go:wasm-module
|
||||
func libc_calloc(nmemb, size uintptr) unsafe.Pointer {
|
||||
// Note: we could be even more correct here and check that nmemb * size
|
||||
// doesn't overflow. However the current implementation should normally work
|
||||
// fine.
|
||||
return alloc(nmemb*size, nil)
|
||||
// No difference between calloc and malloc.
|
||||
return libc_malloc(nmemb * size)
|
||||
}
|
||||
|
||||
//export realloc
|
||||
func libc_realloc(ptr unsafe.Pointer, size uintptr) unsafe.Pointer {
|
||||
return realloc(ptr, size)
|
||||
//go:wasm-module
|
||||
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
|
||||
}
|
||||
|
||||
@@ -10,8 +10,7 @@ import (
|
||||
|
||||
var ErrUnimplemented = errors.New("runtime/pprof: unimplemented")
|
||||
|
||||
type Profile struct {
|
||||
}
|
||||
type Profile struct{}
|
||||
|
||||
func StartCPUProfile(w io.Writer) error {
|
||||
return nil
|
||||
@@ -28,6 +27,18 @@ 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
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
// Stubs for the runtime/trace package
|
||||
package trace
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
)
|
||||
|
||||
func Start(w io.Writer) error {
|
||||
return errors.New("not implemented")
|
||||
}
|
||||
|
||||
func Stop() {}
|
||||
@@ -34,6 +34,17 @@ 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()
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
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,5 +1,5 @@
|
||||
{
|
||||
"inherits": ["esp32c3"],
|
||||
"build-tags": ["esp32c312f", "esp32c3", "esp"]
|
||||
"build-tags": ["esp32c312f"]
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"inherits": ["fe310"],
|
||||
"build-tags": ["hifive1b", "qemu"],
|
||||
"serial": "uart",
|
||||
"default-stack-size": 4096,
|
||||
"linkerscript": "targets/hifive1-qemu.ld",
|
||||
"emulator": "qemu-system-riscv32 -machine sifive_e -nographic -kernel {}"
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
|
||||
/* memory map:
|
||||
* https://github.com/sifive/freedom-e-sdk/blob/v201908-branch/bsp/sifive-hifive1/metal.default.lds
|
||||
* With one change: this linkerscript uses 64K RAM instead of 16K as specified
|
||||
* in metal.default.lds. Not sure why this works, but it works, and it avoids
|
||||
* out-of-memory issues when running tests.
|
||||
*/
|
||||
MEMORY
|
||||
{
|
||||
FLASH_TEXT (rw) : ORIGIN = 0x20400000, LENGTH = 0x1fc00000
|
||||
RAM (xrw) : ORIGIN = 0x80000000, LENGTH = 64K
|
||||
}
|
||||
|
||||
_stack_size = 2K;
|
||||
|
||||
INCLUDE "targets/riscv.ld"
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"inherits": ["atsamd51j19a"],
|
||||
"build-tags": ["atsamd51j19a", "matrixportal_m4"],
|
||||
"build-tags": ["matrixportal_m4"],
|
||||
"serial": "usb",
|
||||
"serial-port": ["acm:239a:80c9", "acm:239a:00c9", "acm:239a:80ca"],
|
||||
"flash-1200-bps-reset": "true",
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
// Adafruit QT Py RP2040 Stage 2 Bootloader
|
||||
|
||||
//
|
||||
// This file defines the parameters specific to the flash-chip found
|
||||
// on the Adafruit QT Py RP2040. The generic implementation is in
|
||||
// rp2040-boot-stage2.S
|
||||
//
|
||||
|
||||
#define BOARD_PICO_FLASH_SPI_CLKDIV 2
|
||||
#define BOARD_CMD_READ 0xe7
|
||||
#define BOARD_QUAD_OK 1
|
||||
#define BOARD_QUAD_ENABLE_STATUS_BYTE 2
|
||||
#define BOARD_QUAD_ENABLE_BIT_MASK 2
|
||||
#define BOARD_SPLIT_STATUS_WRITE 1
|
||||
#define BOARD_WAIT_CYCLES 2
|
||||
|
||||
#include "rp2040-boot-stage2.S"
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"inherits": [
|
||||
"rp2040"
|
||||
],
|
||||
"serial-port": ["acm:239a:80f7"],
|
||||
"build-tags": ["qtpy_rp2040"],
|
||||
"linkerscript": "targets/qtpy-rp2040.ld",
|
||||
"extra-files": [
|
||||
"targets/qtpy-rp2040-boot-stage2.S"
|
||||
],
|
||||
"default-stack-size": 4096
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
MEMORY
|
||||
{
|
||||
/* Reserve exactly 256 bytes at start of flash for second stage bootloader */
|
||||
BOOT2_TEXT (rx) : ORIGIN = 0x10000000, LENGTH = 256
|
||||
FLASH_TEXT (rx) : ORIGIN = 0x10000000 + 256, LENGTH = 8192K - 256
|
||||
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 256k
|
||||
}
|
||||
|
||||
INCLUDE "targets/rp2040.ld"
|
||||
@@ -15,7 +15,6 @@
|
||||
"-msign-ext"
|
||||
],
|
||||
"ldflags": [
|
||||
"--allow-undefined",
|
||||
"--stack-first",
|
||||
"--no-demangle"
|
||||
],
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
syscall/js.copyBytesToGo
|
||||
syscall/js.copyBytesToJS
|
||||
syscall/js.finalizeRef
|
||||
syscall/js.stringVal
|
||||
syscall/js.valueCall
|
||||
syscall/js.valueDelete
|
||||
syscall/js.valueGet
|
||||
syscall/js.valueIndex
|
||||
syscall/js.valueInstanceOf
|
||||
syscall/js.valueInvoke
|
||||
syscall/js.valueLength
|
||||
syscall/js.valueLoadString
|
||||
syscall/js.valueNew
|
||||
syscall/js.valuePrepareString
|
||||
syscall/js.valueSet
|
||||
syscall/js.valueSetIndex
|
||||
+1
-1
@@ -15,7 +15,7 @@
|
||||
"-msign-ext"
|
||||
],
|
||||
"ldflags": [
|
||||
"--allow-undefined",
|
||||
"--allow-undefined-file={root}/targets/wasm-undefined.txt",
|
||||
"--stack-first",
|
||||
"--no-demangle"
|
||||
],
|
||||
|
||||
Vendored
+1
@@ -282,3 +282,4 @@
|
||||
version: master
|
||||
- repo: github.com/russross/blackfriday
|
||||
version: v2
|
||||
- repo: github.com/soypat/mu8
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
//go:build tinygo.wasm
|
||||
// +build tinygo.wasm
|
||||
|
||||
package runtime_wasi
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"testing"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
//export malloc
|
||||
func libc_malloc(size uintptr) unsafe.Pointer
|
||||
|
||||
//export free
|
||||
func libc_free(ptr unsafe.Pointer)
|
||||
|
||||
//export calloc
|
||||
func libc_calloc(nmemb, size uintptr) unsafe.Pointer
|
||||
|
||||
//export realloc
|
||||
func libc_realloc(ptr unsafe.Pointer, size uintptr) unsafe.Pointer
|
||||
|
||||
func getFilledBuffer_malloc() uintptr {
|
||||
ptr := libc_malloc(5)
|
||||
fillPanda(ptr)
|
||||
return uintptr(ptr)
|
||||
}
|
||||
|
||||
func getFilledBuffer_calloc() uintptr {
|
||||
ptr := libc_calloc(2, 5)
|
||||
fillPanda(ptr)
|
||||
*(*byte)(unsafe.Add(ptr, 5)) = 'b'
|
||||
*(*byte)(unsafe.Add(ptr, 6)) = 'e'
|
||||
*(*byte)(unsafe.Add(ptr, 7)) = 'a'
|
||||
*(*byte)(unsafe.Add(ptr, 8)) = 'r'
|
||||
*(*byte)(unsafe.Add(ptr, 9)) = 's'
|
||||
return uintptr(ptr)
|
||||
}
|
||||
|
||||
func getFilledBuffer_realloc() uintptr {
|
||||
origPtr := getFilledBuffer_malloc()
|
||||
ptr := libc_realloc(unsafe.Pointer(origPtr), 9)
|
||||
*(*byte)(unsafe.Add(ptr, 5)) = 'b'
|
||||
*(*byte)(unsafe.Add(ptr, 6)) = 'e'
|
||||
*(*byte)(unsafe.Add(ptr, 7)) = 'a'
|
||||
*(*byte)(unsafe.Add(ptr, 8)) = 'r'
|
||||
return uintptr(ptr)
|
||||
}
|
||||
|
||||
func getFilledBuffer_reallocNil() uintptr {
|
||||
ptr := libc_realloc(nil, 5)
|
||||
fillPanda(ptr)
|
||||
return uintptr(ptr)
|
||||
}
|
||||
|
||||
func fillPanda(ptr unsafe.Pointer) {
|
||||
*(*byte)(unsafe.Add(ptr, 0)) = 'p'
|
||||
*(*byte)(unsafe.Add(ptr, 1)) = 'a'
|
||||
*(*byte)(unsafe.Add(ptr, 2)) = 'n'
|
||||
*(*byte)(unsafe.Add(ptr, 3)) = 'd'
|
||||
*(*byte)(unsafe.Add(ptr, 4)) = 'a'
|
||||
}
|
||||
|
||||
func checkFilledBuffer(t *testing.T, ptr uintptr, content string) {
|
||||
t.Helper()
|
||||
buf := *(*string)(unsafe.Pointer(&reflect.StringHeader{
|
||||
Data: ptr,
|
||||
Len: uintptr(len(content)),
|
||||
}))
|
||||
if buf != content {
|
||||
t.Errorf("expected %q, got %q", content, buf)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMallocFree(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
getBuffer func() uintptr
|
||||
content string
|
||||
}{
|
||||
{
|
||||
name: "malloc",
|
||||
getBuffer: getFilledBuffer_malloc,
|
||||
content: "panda",
|
||||
},
|
||||
{
|
||||
name: "calloc",
|
||||
getBuffer: getFilledBuffer_calloc,
|
||||
content: "pandabears",
|
||||
},
|
||||
{
|
||||
name: "realloc",
|
||||
getBuffer: getFilledBuffer_realloc,
|
||||
content: "pandabear",
|
||||
},
|
||||
{
|
||||
name: "realloc nil",
|
||||
getBuffer: getFilledBuffer_reallocNil,
|
||||
content: "panda",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
tt := tc
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
bufPtr := tt.getBuffer()
|
||||
// Don't use defer to free the buffer as it seems to cause the GC to track it.
|
||||
|
||||
// Churn GC, the pointer should still be valid until free is called.
|
||||
for i := 0; i < 1000; i++ {
|
||||
a := "hello" + strconv.Itoa(i)
|
||||
// Some conditional logic to ensure optimization doesn't remove the loop completely.
|
||||
if len(a) < 0 {
|
||||
break
|
||||
}
|
||||
runtime.GC()
|
||||
}
|
||||
|
||||
checkFilledBuffer(t, bufPtr, tt.content)
|
||||
|
||||
libc_free(unsafe.Pointer(bufPtr))
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user