Compare commits

...

69 Commits

Author SHA1 Message Date
Ayke van Laethem cf0b7edc78 all: release v0.23.0 2022-04-28 17:51:09 +02:00
Damian Gryski a32cda7a4c testdata: move map growth test to map.go 2022-04-28 09:14:45 +02:00
Damian Gryski b251ce7b33 src/runtime: return a nil pointer for compiler bugs in hashmap code
We'll still panic if there's a compiler bug, but at least we'll have smaller
code in all the cases where we don't.
2022-04-28 09:14:45 +02:00
Damian Gryski 1abe1203a3 src/runtime: make hashmap calculations more uintptr-size independent 2022-04-28 09:14:45 +02:00
Damian Gryski 8b360ec911 src/runtime: remove extra if check in hashmap set logic 2022-04-28 09:14:45 +02:00
Damian Gryski 93654544b3 src/runtime: prevent overflow when calculating hashmap growth limits 2022-04-28 09:14:45 +02:00
Damian Gryski 050d516264 testdata: add test for mapgrowth logic 2022-04-28 09:14:45 +02:00
Damian Gryski 9a8328fcb7 src/runtime/hashmap: comments for iterator structure 2022-04-28 09:14:45 +02:00
Damian Gryski 6812a4dc04 src/runtime: first darft of map growth code
Fixes #1553
2022-04-28 09:14:45 +02:00
Ayke van Laethem 8568d4f625 esp32: add support for running and debuggin using qemu-esp32 2022-04-28 07:50:03 +02:00
Ayke van Laethem bd56636d58 all: make emulator command a string instead of a []string
This matches the flash-command and is generally a bit easier to work
with.
This commit also prepares for allowing multiple formats to be used in
the emulator command, which is necessary for the esp32.
2022-04-28 07:50:03 +02:00
Ayke van Laethem 4fe3a379a5 ci: add ARM build, cross compiled on an amd64 host
I'm making this so I don't have to build all the releases on my
Raspberry Pi at home, and to make the process more reproducible.
2022-04-27 22:47:53 +02:00
deadprogram fce42fc7fa machine/thingplus: rename to the singular thing as that it the correct name
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-04-26 21:13:17 +02:00
Ayke van Laethem 5d177d1328 runtime: be able to deal with a very small heap
See the comment in the source for details.

Also see the discussion in
https://github.com/tinygo-org/tinygo/pull/2755, which originally
triggered this bug.

Somewhat surprising, this results in a slight code size decrease for ARM
targets of a few bytes.
2022-04-26 17:47:21 +02:00
lincolngill 9eb4a6268a Pico adc input ch support (#2737)
machine/rp2040: ADC changes, including
* Add rp2040 ADC mux channel support. Internal temp sensor reading and fix for incorrect setting of CS.AINSEL reg bits
* Reset ADC ref voltage in InitADC
2022-04-26 11:49:38 +02:00
deadprogram 11a402de95 docs: update list of currently supported boards
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-04-26 07:47:34 +02:00
Dan Kegel cdd9198888 github: also do tinygo-test-wasi-fast on windows 2022-04-25 17:59:39 +02:00
Dan Kegel 6055e6eb23 Makefile: compress/lzw fails on windows wasi, see #2800, not plain windows. 2022-04-25 17:59:39 +02:00
Dan Kegel 9239c61edb TestChdir: avoid cd .., as wasi does not really support it yet. Tiptoes around #2799. 2022-04-25 17:59:39 +02:00
deadprogram 008b373df4 build: use latest Windows hosted runner version
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-04-25 17:15:59 +02:00
deadprogram c387a09f54 build: use Go 1.18.1 for all builds
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-04-25 17:15:59 +02:00
deadprogram 5bb3ca2618 machine/circuitplay-bluefruit: move pin mappings so board can be compiled for WASM use in Playground
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-04-25 11:17:42 +02:00
Yurii Soldak a4ea85b303 xiao-ble: initial support 2022-04-24 14:50:02 +02:00
Olaf Flebbe 27d38a9663 machine/board_thingsplus_rp2040 targets/thingsplus-rp2040: support sparkfun thingsplus rp2040 board 2022-04-24 10:56:52 +02:00
deadprogram ee497a296b docker: update Dockerfile to use Go 1.18
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-04-23 18:42:00 +02:00
Ayke van Laethem 6b31ee1e93 all: update to LLVM 14
Switch over to LLVM 14 for static builds. Keep using LLVM 13 for regular
builds for now.

This uses a branch of the upstream Espressif branch to fix an issue,
see: https://github.com/espressif/llvm-project/pull/59
2022-04-23 08:45:46 +02:00
Ayke van Laethem cad6a57077 compiler: remove support for memory references in AsmFull
Memory references (`*m` in LLVM IR inline assembly) need a pointer type
starting in LLVM 14. This is a bit inconvenient and requires a new API
in the go-llvm package.

Instead of doing that, I'd like to remove support for memory references
from AsmFull (and possibly AsmFull entirely if possible: it's hard to
use correctly).

This breaks tinygo.org/x/drivers/ws2812 for AVR, ARM, and RISC-V which
need to be updated. Probably using CGo.
2022-04-21 15:18:18 +02:00
Ayke van Laethem 52233790cc mimxrt1062: simplify arm.AsmFull to arm.Asm
This means fewer instances of arm.AsmFull, which I'd like to remove
eventually if possible.
2022-04-21 15:18:18 +02:00
Ayke van Laethem 9160f3f16d main: use shared code for both run and test subcommands
This means that we don't need duplicate code to pass parameters to
wasmtime and that the following actually produces verbose output (it
didn't before this commit):

    tinygo test -v -target=cortex-m-qemu math
2022-04-20 08:22:46 +02:00
Dan Kegel 69d7ed5cda os: define ErrDeadlineExceeded; fixes go 1.18 compile error in net/http, #2782 2022-04-19 09:22:27 +02:00
Dan Kegel 111661658b .github: use proper name for Mac OS 11 (10.16 was unofficial; we could also use 10.15) 2022-04-18 22:52:14 +02:00
Dan Kegel 3000b2d15e gofmt src/machine/machine_mimxrt1062_spi.go to please 1.18 2022-04-18 22:52:14 +02:00
Dan Kegel c89f026532 Makefile: tinygo-test: skip compress/flate test on windows for now
Lets us move forward until
https://github.com/tinygo-org/tinygo/issues/2762
is fixed.
2022-04-18 22:52:14 +02:00
Dan Kegel e09b1d06f5 Smoke test 1.15 still until we drop support for it 2022-04-18 22:52:14 +02:00
Dan Kegel 0590ccb260 gofmt exec_posix.go 2022-04-18 22:52:14 +02:00
Dan Kegel fe0acb1670 ci: updated supported go versions from 1.15-1.17 to 1.16-1.18 2022-04-18 22:52:14 +02:00
Ayke van Laethem d58c7d2521 main: add support for command-line parameters to tinygo run
This is made easy by the refactor in the previous commit.
2022-04-16 18:37:03 +02:00
Ayke van Laethem 85f5411d60 main: unify how a given program runs
Refactor the code that runs a binary. With this change, the slightly
duplicated code between `tinygo run` and `TestBuild` is merged into one.
Apart from deduplication (which doesn't even gain much in terms of lines
removed), it makes it much easier to maintain this code. In particular,
passing command line arguments to programs to run now becomes trivial.

A future change might also merge `buildAndRun` and `runPackageTest`,
which currently have some overlap. In particular, flags like `-test.v`
don't need to be special-cased for wasmtime.
2022-04-16 18:37:03 +02:00
ardnew c5de68622e board/teensy40: Add SPI support (#1455)
machine/teensy40: add SPI support
2022-04-16 15:43:52 +02:00
Ayke van Laethem 8fb93fbac4 esp: support CGo
Without this patch, the include directory isn't found and picolibc.h
(used indirectly by stdint.h for example) can't be found.

I would like to add tests for this but we currently don't run Xtensa
tests. This should be possible however using https://github.com/espressif/qemu/wiki
(see also: https://github.com/tinygo-org/tinygo/pull/2780).
2022-04-15 23:28:26 +02:00
Ayke van Laethem ef3b3c0d6a transform: fix poison value in heap-to-stack transform
In https://github.com/tinygo-org/tinygo/issues/2777, a poison value
ended up in `runtime.alloc`. This shouldn't happen, especially not for
well written code. So I'm not sure why it happens. But here is a fix
anyway.
2022-04-15 22:54:25 +02:00
ardnew 2dc46a851b board/teensy40: Add ADC support (#1458)
machine/teensy40: add ADC support
2022-04-13 17:12:31 +02:00
Ron Evans f3afc7bbf3 Revert "fix: flash-command for maixbit board"
This reverts commit b02cea0321.
2022-04-12 17:13:32 +02:00
Elliott Sales de Andrade 4858b27120 Also disable asynchronous unwind tables
These seem to be enabled in LLVM 14, and cause undefined symbol errors.
2022-04-11 14:58:55 +02:00
Elliott Sales de Andrade 7f507a7026 Fix incorrect formatting arguments 2022-04-10 22:58:16 +02:00
Ayke van Laethem 83227e68df all: use compiler-rt from LLVM 2022-04-10 21:03:59 +02:00
sago35 09a3c6a16b flash: add openocd-verify 2022-04-09 17:49:54 +02:00
soypat f613cb41a3 rp2040: fix spurious i2c STOP during write+read transaction 2022-04-09 11:10:36 +02:00
Elias Naur e060e588ab goenv: look for Go version in $GOROOT/src/internal/buildcfg/zbootstrap.go
The old path, $GOROOT/runtime/internal/sys/zversion.go, no longer contains
the Go version.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2022-04-09 10:11:07 +02:00
Dan Kegel 8dfb317d28 Allow building with go 1.18 2022-04-09 09:16:37 +02:00
Elliott Sales de Andrade 9cedd78d9c Add a shim for internal/fuzz
This simply shadows the real code temporarily to see what else is
broken. It only defines a single type to fix testing/internal/testdeps.
2022-04-09 09:16:37 +02:00
Dan Kegel 20a27746b2 compiler: make RawSyscall an alias for Syscall per suggestion from Ayke. For #2474. 2022-04-08 08:29:30 +02:00
Dan Kegel c78df85015 os: Implement Pipe for darwin, add smoke test.
Evidently when you read from pipes in Go, you have to adjust your slice length to reflect the number of bytes read.
Verified upstream behaves the same way.
2022-04-08 08:29:30 +02:00
Ayke van Laethem c0d257d682 compiler: fix difference in aliases in interface methods
There used to be a difference between `byte` and `uint8` in interface
methods. These are aliases, so they should be treated the same.
This patch introduces a custom serialization format for types,
circumventing the `Type.String()` method that is slightly wrong for our
purposes.

This also fixes an issue with the `any` keyword in Go 1.18, which
suffers from the same problem (but this time actually leads to a crash).
2022-04-07 12:54:17 +02:00
Dan Kegel 7af24c7864 compiler: allow slices of empty structs.
Fixes https://github.com/tinygo-org/tinygo/issues/2749
2022-04-07 12:00:27 +02:00
Dan Kegel 3dc1e403ea runtime: stub {Lock,Unlock}OSThread. Makes 1.18 happier on windows. 2022-04-07 10:27:34 +02:00
sago35 1deee3ec5a m5stamp-c3: add pin setting of UART 2022-04-07 07:16:27 +02:00
Dan Kegel 0f9f316db2 main_test.go: fork testdata/testing.go for go 1.18 2022-04-06 20:03:04 +02:00
Dmitriy 0dd521e1d1 add support for esp32c3 to receive UART data 2022-04-06 19:25:24 +02:00
Ron Evans 1dcdd5f2d2 Revert "src/runtime: first darft of map growth code"
This reverts commit 7e05efa274.
2022-04-05 03:34:01 +02:00
Ron Evans dcd8ee63a8 Revert "src/runtime/hashmap: comments for iterator structure"
This reverts commit 8872229a0b.
2022-04-05 03:34:01 +02:00
Ron Evans b8bf0ac3f1 Revert "testdata: add test for mapgrowth logic"
This reverts commit 73571dd423.
2022-04-05 03:34:01 +02:00
Damian Gryski 73571dd423 testdata: add test for mapgrowth logic 2022-04-04 13:22:19 +02:00
Damian Gryski 8872229a0b src/runtime/hashmap: comments for iterator structure 2022-04-04 13:22:19 +02:00
Damian Gryski 7e05efa274 src/runtime: first darft of map growth code
Fixes #1553
2022-04-04 13:22:19 +02:00
Sai Sasidhar Maddali b02cea0321 fix: flash-command for maixbit board
Latest version of kflash tool requires a --Board/-B argument to
        be able to run the tool
2022-04-04 09:15:39 +02:00
Dan Kegel 8823a934a3 syscall: stub WaitStatus 2022-04-04 07:33:31 +02:00
Dan Kegel 6ac02cc34c syscall: wasi: more complete list of signals
Grepped straight out of the appropriate signal.h, with order preserved.

Makes 1.18 tests happier.

See comment on discrepancy for SIGCHLD.  Since wasi doesn't really support signals, this may not matter.
2022-04-03 19:22:43 +02:00
Dan Kegel e259598b68 syscall: darwin: more complete list of signals
Grepped straight out of the appropriate signal.h, with order and comments preserved verbatim.

Makes 1.18 tests happier.
2022-04-03 19:22:43 +02:00
123 changed files with 2985 additions and 774 deletions
+8 -7
View File
@@ -22,15 +22,16 @@ commands:
steps:
- restore_cache:
keys:
- llvm-source-13-v1
- llvm-source-14-v1
- run:
name: "Fetch LLVM source"
command: make llvm-source
- save_cache:
key: llvm-source-13-v1
key: llvm-source-14-v1
paths:
- llvm-project/clang/lib/Headers
- llvm-project/clang/include
- llvm-project/compiler-rt
- llvm-project/lld/include
- llvm-project/llvm/include
hack-ninja-jobs:
@@ -85,10 +86,10 @@ commands:
- run: go install -tags=llvm<<parameters.llvm>> .
- restore_cache:
keys:
- wasi-libc-sysroot-systemclang-v4
- wasi-libc-sysroot-systemclang-v5
- run: make wasi-libc
- save_cache:
key: wasi-libc-sysroot-systemclang-v4
key: wasi-libc-sysroot-systemclang-v5
paths:
- lib/wasi-libc/sysroot
- run: make gen-device -j4
@@ -107,9 +108,9 @@ jobs:
steps:
- test-linux:
llvm: "11"
test-llvm12-go116:
test-llvm12-go117:
docker:
- image: circleci/golang:1.16-buster
- image: circleci/golang:1.17-buster
steps:
- test-linux:
llvm: "12"
@@ -118,4 +119,4 @@ workflows:
test-all:
jobs:
- test-llvm11-go115
- test-llvm12-go116
- test-llvm12-go117
+6 -5
View File
@@ -10,12 +10,12 @@ on:
jobs:
build-macos:
name: build-macos
runs-on: macos-10.15
runs-on: macos-11
steps:
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: '1.17'
go-version: '1.18.1'
- name: Install Dependencies
shell: bash
run: |
@@ -35,10 +35,11 @@ jobs:
uses: actions/cache@v2
id: cache-llvm-source
with:
key: llvm-source-13-macos-v1
key: llvm-source-14-macos-v1
path: |
llvm-project/clang/lib/Headers
llvm-project/clang/include
llvm-project/compiler-rt
llvm-project/lld/include
llvm-project/llvm/include
- name: Download LLVM source
@@ -48,7 +49,7 @@ jobs:
uses: actions/cache@v2
id: cache-llvm-build
with:
key: llvm-build-13-macos-v3
key: llvm-build-14-macos-v1
path: llvm-build
- name: Build LLVM
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
@@ -66,7 +67,7 @@ jobs:
uses: actions/cache@v2
id: cache-wasi-libc
with:
key: wasi-libc-sysroot-v2
key: wasi-libc-sysroot-v3
path: lib/wasi-libc/sysroot
- name: Build wasi-libc
if: steps.cache-wasi-libc.outputs.cache-hit != 'true'
+118 -12
View File
@@ -26,7 +26,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: '1.17'
go-version: '1.18.1'
- name: Cache Go
uses: actions/cache@v2
with:
@@ -38,10 +38,11 @@ jobs:
uses: actions/cache@v2
id: cache-llvm-source
with:
key: llvm-source-13-linux-v1
key: llvm-source-14-linux-v1
path: |
llvm-project/clang/lib/Headers
llvm-project/clang/include
llvm-project/compiler-rt
llvm-project/lld/include
llvm-project/llvm/include
- name: Download LLVM source
@@ -51,7 +52,7 @@ jobs:
uses: actions/cache@v2
id: cache-llvm-build
with:
key: llvm-build-13-linux-v2
key: llvm-build-14-linux-v1
path: llvm-build
- name: Build LLVM
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
@@ -76,14 +77,13 @@ jobs:
uses: actions/cache@v2
id: cache-wasi-libc
with:
key: wasi-libc-sysroot-linux-asserts-v3
key: wasi-libc-sysroot-linux-asserts-v4
path: lib/wasi-libc/sysroot
- name: Build wasi-libc
if: steps.cache-wasi-libc.outputs.cache-hit != 'true'
run: make wasi-libc
- name: Install fpm
run: |
sudo apt-get install ruby ruby-dev
sudo gem install --no-document fpm
- name: Build TinyGo release
run: |
@@ -93,7 +93,7 @@ jobs:
- name: Publish release artifact
uses: actions/upload-artifact@v2
with:
name: release-double-zipped
name: linux-amd64-double-zipped
path: |
/tmp/tinygo.linux-amd64.tar.gz
/tmp/tinygo_amd64.deb
@@ -107,7 +107,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: '1.17'
go-version: '1.18.1'
- name: Install wasmtime
run: |
curl https://wasmtime.dev/install.sh -sSf | bash
@@ -115,7 +115,7 @@ jobs:
- name: Download release artifact
uses: actions/download-artifact@v2
with:
name: release-double-zipped
name: linux-amd64-double-zipped
- name: Extract release tarball
run: |
mkdir -p ~/lib
@@ -159,7 +159,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: '1.17'
go-version: '1.18.1'
- name: Install Node.js
uses: actions/setup-node@v2
with:
@@ -179,10 +179,11 @@ jobs:
uses: actions/cache@v2
id: cache-llvm-source
with:
key: llvm-source-13-linux-asserts-v1
key: llvm-source-14-linux-asserts-v1
path: |
llvm-project/clang/lib/Headers
llvm-project/clang/include
llvm-project/compiler-rt
llvm-project/lld/include
llvm-project/llvm/include
- name: Download LLVM source
@@ -192,7 +193,7 @@ jobs:
uses: actions/cache@v2
id: cache-llvm-build
with:
key: llvm-build-13-linux-asserts-v2
key: llvm-build-14-linux-asserts-v1
path: llvm-build
- name: Build LLVM
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
@@ -217,7 +218,7 @@ jobs:
uses: actions/cache@v2
id: cache-wasi-libc
with:
key: wasi-libc-sysroot-linux-asserts-v3
key: wasi-libc-sysroot-linux-asserts-v4
path: lib/wasi-libc/sysroot
- name: Build wasi-libc
if: steps.cache-wasi-libc.outputs.cache-hit != 'true'
@@ -240,3 +241,108 @@ jobs:
- run: make smoketest
- run: make wasmtest
- run: make tinygo-baremetal
build-linux-arm:
# Build ARM Linux binaries, ready for release.
# This intentionally uses an older Linux image, so that we compile against
# an older glibc version and therefore are compatible with a wide range of
# Linux distributions.
# It is set to "needs: build-linux" because it modifies the release created
# in that process to avoid doing lots of duplicate work and to avoid
# complications around precompiled libraries such as compiler-rt shipped as
# part of the release tarball.
runs-on: ubuntu-18.04
needs: build-linux
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install apt dependencies
run: |
sudo apt-get install --no-install-recommends \
qemu-user \
g++-arm-linux-gnueabihf \
libc6-dev-armhf-cross
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: '1.17'
- 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@v2
id: cache-llvm-source
with:
key: llvm-source-14-linux-v1
path: |
llvm-project/clang/lib/Headers
llvm-project/clang/include
llvm-project/compiler-rt
llvm-project/lld/include
llvm-project/llvm/include
- name: Download LLVM source
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
run: make llvm-source
- name: Cache LLVM build
uses: actions/cache@v2
id: cache-llvm-build
with:
key: llvm-build-14-linux-arm-v1
path: llvm-build
- name: Build LLVM
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
run: |
# fetch LLVM source
rm -rf llvm-project
make llvm-source
# Install build dependencies.
sudo apt-get install --no-install-recommends ninja-build
# build!
make llvm-build CROSS=arm-linux-gnueabihf
# Remove unnecessary object files (to reduce cache size).
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
- name: Cache Binaryen
uses: actions/cache@v2
id: cache-binaryen
with:
key: binaryen-linux-arm-v1
path: build/wasm-opt
- name: Build Binaryen
if: steps.cache-binaryen.outputs.cache-hit != 'true'
run: |
sudo apt-get install --no-install-recommends ninja-build
git submodule update --init lib/binaryen
make CROSS=arm-linux-gnueabihf binaryen
- name: Install fpm
run: |
sudo gem install --no-document fpm
- name: Build TinyGo binary
run: |
make CROSS=arm-linux-gnueabihf
- name: Download amd64 release
uses: actions/download-artifact@v2
with:
name: linux-amd64-double-zipped
- name: Extract amd64 release
run: |
mkdir -p build/release
tar -xf tinygo.linux-amd64.tar.gz -C build/release tinygo
- name: Modify release
run: |
cp -p build/tinygo build/release/tinygo/bin
cp -p build/wasm-opt build/release/tinygo/bin
- name: Create arm release
run: |
make release deb RELEASEONLY=1 DEB_ARCH=armhf
cp -p build/release.tar.gz /tmp/tinygo.linux-arm.tar.gz
cp -p build/release.deb /tmp/tinygo_armhf.deb
- name: Publish release artifact
uses: actions/upload-artifact@v2
with:
name: linux-arm-double-zipped
path: |
/tmp/tinygo.linux-arm.tar.gz
/tmp/tinygo_armhf.deb
+11 -5
View File
@@ -9,12 +9,12 @@ on:
jobs:
build-windows:
runs-on: windows-2019
runs-on: windows-2022
steps:
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: '1.17'
go-version: '1.18.1'
- uses: brechtm/setup-scoop@v2
- name: Install Dependencies
shell: bash
@@ -35,10 +35,11 @@ jobs:
uses: actions/cache@v2
id: cache-llvm-source
with:
key: llvm-source-13-windows-v1
key: llvm-source-14-windows-v1
path: |
llvm-project/clang/lib/Headers
llvm-project/clang/include
llvm-project/compiler-rt
llvm-project/lld/include
llvm-project/llvm/include
- name: Download LLVM source
@@ -48,7 +49,7 @@ jobs:
uses: actions/cache@v2
id: cache-llvm-build
with:
key: llvm-build-13-windows-v2
key: llvm-build-14-windows-v1
path: llvm-build
- name: Build LLVM
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
@@ -65,11 +66,14 @@ jobs:
uses: actions/cache@v2
id: cache-wasi-libc
with:
key: wasi-libc-sysroot-v2
key: wasi-libc-sysroot-v3
path: lib/wasi-libc/sysroot
- name: Build wasi-libc
if: steps.cache-wasi-libc.outputs.cache-hit != 'true'
run: make wasi-libc
- name: Install wasmtime
run: |
scoop install wasmtime
- name: Test TinyGo
shell: bash
run: make test GOTESTFLAGS="-v -short"
@@ -95,3 +99,5 @@ jobs:
run: make smoketest TINYGO=$(PWD)/build/tinygo AVR=0 XTENSA=0
- name: Test stdlib packages
run: make tinygo-test
- name: Test stdlib packages on wasi
run: make tinygo-test-wasi-fast
-4
View File
@@ -10,10 +10,6 @@
[submodule "lib/cmsis-svd"]
path = lib/cmsis-svd
url = https://github.com/tinygo-org/cmsis-svd
[submodule "lib/compiler-rt"]
path = lib/compiler-rt
url = https://github.com/llvm-mirror/compiler-rt.git
branch = release_80
[submodule "lib/wasi-libc"]
path = lib/wasi-libc
url = https://github.com/CraneStation/wasi-libc
+98
View File
@@ -1,3 +1,101 @@
0.23.0
---
* **command line**
- add `-work` flag
- add Go 1.18 support
- add LLVM 14 support
- `run`: add support for command-line parameters
- `build`: calculate default output path if `-o` is not specified
- `build`: add JSON output
- `test`: support multiple test binaries with `-c`
- `test`: support flags like `-v` on all targets (including emulated firmware)
* **compiler**
- add support for ThinLTO
- use compiler-rt from LLVM
- `builder`: prefer GNU build ID over Go build ID for caching
- `builder`: add support for cross compiling to Darwin
- `builder`: support machine outlining pass in stacksize calculation
- `builder`: disable asynchronous unwind tables
- `compileopts`: fix emulator configuration on non-amd64 Linux architectures
- `compiler`: move allocations > 256 bytes to the heap
- `compiler`: fix incorrect `unsafe.Alignof` on some 32-bit architectures
- `compiler`: accept alias for slice `cap` builtin
- `compiler`: allow slices of empty structs
- `compiler`: fix difference in aliases in interface methods
- `compiler`: make `RawSyscall` an alias for `Syscall`
- `compiler`: remove support for memory references in `AsmFull`
- `loader`: only add Clang header path for CGo
- `transform`: fix poison value in heap-to-stack transform
* **standard library**
- `internal/fuzz`: add this package as a shim
- `os`: implement readdir for darwin and linux
- `os`: add `DirFS`, which is used by many programs to access readdir.
- `os`: isWine: be compatible with older versions of wine, too
- `os`: implement `RemoveAll`
- `os`: Use a `uintptr` for `NewFile`
- `os`: add stubs for `exec.ExitError` and `ProcessState.ExitCode`
- `os`: export correct values for `DevNull` for each OS
- `os`: improve support for `Signal` by fixing various bugs
- `os`: implement `File.Fd` method
- `os`: implement `UserHomeDir`
- `os`: add `exec.ProcessState` stub
- `os`: implement `Pipe` for darwin
- `os`: define stub `ErrDeadlineExceeded`
- `reflect`: add stubs for more missing methods
- `reflect`: rename `reflect.Ptr` to `reflect.Pointer`
- `reflect`: add `Value.FieldByIndexErr` stub
- `runtime`: fix various small GC bugs
- `runtime`: use memzero for leaking collector instead of manually zeroing objects
- `runtime`: implement `memhash`
- `runtime`: implement `fastrand`
- `runtime`: add stub for `debug.ReadBuildInfo`
- `runtime`: add stub for `NumCPU`
- `runtime`: don't inline `runtime.alloc` with `-gc=leaking`
- `runtime`: add `Version`
- `runtime`: add stubs for `NumCgoCall` and `NumGoroutine`
- `runtime`: stub {Lock,Unlock}OSThread on Windows
- `runtime`: be able to deal with a very small heap
- `syscall`: make `Environ` return a copy of the environment
- `syscall`: implement getpagesize and munmap
- `syscall`: `wasi`: define `MAP_SHARED` and `PROT_READ`
- `syscall`: stub mmap(), munmap(), MAP_SHARED, PROT_READ, SIGBUS, etc. on nonhosted targets
- `syscall`: darwin: more complete list of signals
- `syscall`: `wasi`: more complete list of signals
- `syscall`: stub `WaitStatus`
- `syscall/js`: allow copyBytesTo(Go|JS) to use `Uint8ClampedArray`
- `testing`: implement `TempDir`
- `testing`: nudge type TB closer to upstream; should be a no-op change.
- `testing`: on baremetal platforms, use simpler test matcher
* **targets**
- `atsamd`: fix usbcdc initialization when `-serial=uart`
- `atsamd51`: allow higher frequency when using SPI
- `esp`: support CGo
- `esp32c3`: add support for input pin
- `esp32c3`: add support for GPIO interrupts
- `esp32c3`: add support to receive UART data
- `rp2040`: fix PWM bug at high frequency
- `rp2040`: fix some minor I2C bugs
- `rp2040`: fix incorrect inline assembly
- `rp2040`: fix spurious i2c STOP during write+read transaction
- `rp2040`: improve ADC support
- `wasi`: remove `--export-dynamic` linker flag
- `wasm`: remove heap allocator from wasi-libc
* **boards**
- `circuitplay-bluefruit`: move pin mappings so board can be compiled for WASM use in Playground
- `esp32-c3-12f`: add the ESP32-C3-12f Kit
- `m5stamp-c3`: add pin setting of UART
- `macropad-rp2040`: add the Adafruit MacroPad RP2040 board
- `nano-33-ble`: typo in LPS22HB peripheral definition and documentation (#2579)
- `teensy41`: add the Teensy 4.1 board
- `teensy40`: add ADC support
- `teensy40`: add SPI support
- `thingplus-rp2040`: add the SparkFun Thing Plus RP2040 board
- `wioterminal`: add DefaultUART
- `wioterminal`: verify written data when flashing through OpenOCD
- `xiao-ble`: add XIAO BLE nRF52840 support
0.22.0
---
+1 -1
View File
@@ -1,5 +1,5 @@
# tinygo-llvm stage obtains the llvm source for TinyGo
FROM golang:1.17 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
+51 -18
View File
@@ -10,7 +10,7 @@ LLD_SRC ?= $(LLVM_PROJECTDIR)/lld
# Try to autodetect LLVM build tools.
# Versions are listed here in descending priority order.
LLVM_VERSIONS = 13 12 11
LLVM_VERSIONS = 14 13 12 11
errifempty = $(if $(1),$(1),$(error $(2)))
detect = $(shell which $(call errifempty,$(firstword $(foreach p,$(2),$(shell command -v $(p) 2> /dev/null && echo $(p)))),failed to locate $(1) at any of: $(2)))
toolSearchPathsVersion = $(1)-$(2)
@@ -50,6 +50,29 @@ else
LLVM_OPTION += '-DLLVM_ENABLE_ASSERTIONS=OFF'
endif
# Cross compiling support.
ifneq ($(CROSS),)
CC = $(CROSS)-gcc
CXX = $(CROSS)-g++
LLVM_OPTION += \
-DCMAKE_C_COMPILER=$(CC) \
-DCMAKE_CXX_COMPILER=$(CXX) \
-DLLVM_DEFAULT_TARGET_TRIPLE=$(CROSS) \
-DCROSS_TOOLCHAIN_FLAGS_NATIVE="-UCMAKE_C_COMPILER;-UCMAKE_CXX_COMPILER"
ifeq ($(CROSS), arm-linux-gnueabihf)
# Assume we're building on a Debian-like distro, with QEMU installed.
LLVM_CONFIG_PREFIX = qemu-arm -L /usr/arm-linux-gnueabihf/
# The CMAKE_SYSTEM_NAME flag triggers cross compilation mode.
LLVM_OPTION += \
-DCMAKE_SYSTEM_NAME=Linux \
-DLLVM_TARGET_ARCH=ARM
GOENVFLAGS = GOARCH=arm CC=$(CC) CXX=$(CXX) CGO_ENABLED=1
BINARYEN_OPTION += -DCMAKE_C_COMPILER=$(CC) -DCMAKE_CXX_COMPILER=$(CXX)
else
$(error Unknown cross compilation target: $(CROSS))
endif
endif
.PHONY: all tinygo test $(LLVM_BUILDDIR) llvm-source clean fmt gen-device gen-device-nrf gen-device-nxp gen-device-avr gen-device-rp
LLVM_COMPONENTS = all-targets analysis asmparser asmprinter bitreader bitwriter codegen core coroutines coverage debuginfodwarf debuginfopdb executionengine frontendopenmp instrumentation interpreter ipo irreader libdriver linker lto mc mcjit objcarcopts option profiledata scalaropts support target windowsmanifest
@@ -91,11 +114,11 @@ CLANG_LIB_NAMES = clangAnalysis clangAST clangASTMatchers clangBasic clangCodeGe
CLANG_LIBS = $(START_GROUP) $(addprefix -l,$(CLANG_LIB_NAMES)) $(END_GROUP) -lstdc++
# Libraries that should be linked in for the statically linked LLD.
LLD_LIB_NAMES = lldCOFF lldCommon lldCore lldDriver lldELF lldMachO2 lldMinGW lldReaderWriter lldWasm lldYAML
LLD_LIB_NAMES = lldCOFF lldCommon lldELF lldMachO lldMinGW lldWasm
LLD_LIBS = $(START_GROUP) $(addprefix -l,$(LLD_LIB_NAMES)) $(END_GROUP)
# Other libraries that are needed to link TinyGo.
EXTRA_LIB_NAMES = LLVMInterpreter
EXTRA_LIB_NAMES = LLVMInterpreter LLVMMCA LLVMX86TargetMCA
# All libraries to be built and linked with the tinygo binary (lib/lib*.a).
LIB_NAMES = clang $(CLANG_LIB_NAMES) $(LLD_LIB_NAMES) $(EXTRA_LIB_NAMES)
@@ -110,9 +133,9 @@ NINJA_BUILD_TARGETS = clang llvm-config llvm-ar llvm-nm $(addprefix lib/lib,$(ad
# For static linking.
ifneq ("$(wildcard $(LLVM_BUILDDIR)/bin/llvm-config*)","")
CGO_CPPFLAGS+=$(shell $(LLVM_BUILDDIR)/bin/llvm-config --cppflags) -I$(abspath $(LLVM_BUILDDIR))/tools/clang/include -I$(abspath $(CLANG_SRC))/include -I$(abspath $(LLD_SRC))/include
CGO_CPPFLAGS+=$(shell $(LLVM_CONFIG_PREFIX) $(LLVM_BUILDDIR)/bin/llvm-config --cppflags) -I$(abspath $(LLVM_BUILDDIR))/tools/clang/include -I$(abspath $(CLANG_SRC))/include -I$(abspath $(LLD_SRC))/include
CGO_CXXFLAGS=-std=c++14
CGO_LDFLAGS+=-L$(abspath $(LLVM_BUILDDIR)/lib) -lclang $(CLANG_LIBS) $(LLD_LIBS) $(shell $(LLVM_BUILDDIR)/bin/llvm-config --ldflags --libs --system-libs $(LLVM_COMPONENTS)) -lstdc++ $(CGO_LDFLAGS_EXTRA)
CGO_LDFLAGS+=-L$(abspath $(LLVM_BUILDDIR)/lib) -lclang $(CLANG_LIBS) $(LLD_LIBS) $(shell $(LLVM_CONFIG_PREFIX) $(LLVM_BUILDDIR)/bin/llvm-config --ldflags --libs --system-libs $(LLVM_COMPONENTS)) -lstdc++ $(CGO_LDFLAGS_EXTRA)
endif
clean:
@@ -175,7 +198,7 @@ gen-device-rp: build/gen-device-svd
# Get LLVM sources.
$(LLVM_PROJECTDIR)/llvm:
git clone -b xtensa_release_13.0.0 --depth=1 https://github.com/tinygo-org/llvm-project $(LLVM_PROJECTDIR)
git clone -b xtensa_release_14.0.0-patched --depth=1 https://github.com/tinygo-org/llvm-project $(LLVM_PROJECTDIR)
llvm-source: $(LLVM_PROJECTDIR)/llvm
# Configure LLVM.
@@ -208,21 +231,18 @@ lib/wasi-libc/sysroot/lib/wasm32-wasi/libc.a:
# Build the Go compiler.
tinygo:
@if [ ! -f "$(LLVM_BUILDDIR)/bin/llvm-config" ]; then echo "Fetch and build LLVM first by running:"; echo " make llvm-source"; echo " make $(LLVM_BUILDDIR)"; exit 1; fi
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) build -buildmode exe -o build/tinygo$(EXE) -tags byollvm -ldflags="-X github.com/tinygo-org/tinygo/goenv.GitSha1=`git rev-parse --short HEAD`" .
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GOENVFLAGS) $(GO) build -buildmode exe -o build/tinygo$(EXE) -tags byollvm -ldflags="-X github.com/tinygo-org/tinygo/goenv.GitSha1=`git rev-parse --short HEAD`" .
test: wasi-libc
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test $(GOTESTFLAGS) -timeout=20m -buildmode exe -tags byollvm ./builder ./cgo ./compileopts ./compiler ./interp ./transform .
# Standard library packages that pass tests on darwin, linux, wasi, and windows, but take over a minute in wasi
TEST_PACKAGES_SLOW = \
compress/bzip2 \
compress/flate \
crypto/dsa \
index/suffixarray \
# Standard library packages that pass tests quickly on darwin, linux, wasi, and windows
TEST_PACKAGES_FAST = \
compress/lzw \
compress/zlib \
container/heap \
container/list \
@@ -269,10 +289,14 @@ TEST_PACKAGES_FAST = \
# 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
# 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 := \
archive/zip \
compress/flate \
compress/lzw \
debug/dwarf \
debug/plan9obj \
io/fs \
@@ -280,6 +304,9 @@ TEST_PACKAGES_LINUX := \
TEST_PACKAGES_DARWIN := $(TEST_PACKAGES_LINUX)
TEST_PACKAGES_WINDOWS := \
compress/lzw
# Report platforms on which each standard library package is known to pass tests
jointmp := $(shell echo /tmp/join.$$$$)
report-stdlib-tests-pass:
@@ -298,7 +325,7 @@ ifeq ($(shell uname),Linux)
TEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_LINUX)
endif
ifeq ($(OS),Windows_NT)
TEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST)
TEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_WINDOWS)
endif
# Test known-working standard library packages.
@@ -388,6 +415,8 @@ ifneq ($(WASM), 0)
@$(MD5SUM) test.wasm
$(TINYGO) build -size short -o test.wasm -tags=circuitplay_express examples/blinky1
@$(MD5SUM) test.wasm
$(TINYGO) build -size short -o test.wasm -tags=circuitplay_bluefruit examples/blinky1
@$(MD5SUM) test.wasm
endif
# test all targets/boards
$(TINYGO) build -size short -o test.hex -target=pca10040-s132v6 examples/blinky1
@@ -619,7 +648,6 @@ build/release: tinygo gen-device wasi-libc $(if $(filter 1,$(USE_SYSTEM_BINARYEN
@mkdir -p build/release/tinygo/bin
@mkdir -p build/release/tinygo/lib/clang/include
@mkdir -p build/release/tinygo/lib/CMSIS/CMSIS
@mkdir -p build/release/tinygo/lib/compiler-rt/lib
@mkdir -p build/release/tinygo/lib/macos-minimal-sdk
@mkdir -p build/release/tinygo/lib/mingw-w64/mingw-w64-crt/lib-common
@mkdir -p build/release/tinygo/lib/mingw-w64/mingw-w64-headers/defaults
@@ -641,9 +669,6 @@ endif
@cp -p $(abspath $(CLANG_SRC))/lib/Headers/*.h build/release/tinygo/lib/clang/include
@cp -rp lib/CMSIS/CMSIS/Include build/release/tinygo/lib/CMSIS/CMSIS
@cp -rp lib/CMSIS/README.md build/release/tinygo/lib/CMSIS
@cp -rp lib/compiler-rt/lib/builtins build/release/tinygo/lib/compiler-rt/lib
@cp -rp lib/compiler-rt/LICENSE.TXT build/release/tinygo/lib/compiler-rt
@cp -rp lib/compiler-rt/README.txt build/release/tinygo/lib/compiler-rt
@cp -rp lib/macos-minimal-sdk/* build/release/tinygo/lib/macos-minimal-sdk
@cp -rp lib/musl/arch/aarch64 build/release/tinygo/lib/musl/arch
@cp -rp lib/musl/arch/arm build/release/tinygo/lib/musl/arch
@@ -680,6 +705,8 @@ endif
@cp -rp lib/picolibc/newlib/libm/common build/release/tinygo/lib/picolibc/newlib/libm
@cp -rp lib/picolibc-stdio.c build/release/tinygo/lib
@cp -rp lib/wasi-libc/sysroot build/release/tinygo/lib/wasi-libc/sysroot
@cp -rp llvm-project/compiler-rt/lib/builtins build/release/tinygo/lib/compiler-rt-builtins
@cp -rp llvm-project/compiler-rt/LICENSE.TXT build/release/tinygo/lib/compiler-rt-builtins
@cp -rp src build/release/tinygo/src
@cp -rp targets build/release/tinygo/targets
./build/tinygo build-library -target=cortex-m0 -o build/release/tinygo/pkg/thumbv6m-unknown-unknown-eabi-cortex-m0/compiler-rt compiler-rt
@@ -689,12 +716,18 @@ endif
./build/tinygo build-library -target=cortex-m0plus -o build/release/tinygo/pkg/thumbv6m-unknown-unknown-eabi-cortex-m0plus/picolibc picolibc
./build/tinygo build-library -target=cortex-m4 -o build/release/tinygo/pkg/thumbv7em-unknown-unknown-eabi-cortex-m4/picolibc picolibc
release: build/release
release:
tar -czf build/release.tar.gz -C build/release tinygo
deb: build/release
DEB_ARCH ?= native
deb:
@mkdir -p build/release-deb/usr/local/bin
@mkdir -p build/release-deb/usr/local/lib
cp -ar build/release/tinygo build/release-deb/usr/local/lib/tinygo
ln -sf ../lib/tinygo/bin/tinygo build/release-deb/usr/local/bin/tinygo
fpm -f -s dir -t deb -n tinygo -v $(shell grep "const Version = " goenv/version.go | awk '{print $$NF}') -m '@tinygo-org' --description='TinyGo is a Go compiler for small places.' --license='BSD 3-Clause' --url=https://tinygo.org/ --deb-changelog CHANGELOG.md -p build/release.deb -C ./build/release-deb
fpm -f -s dir -t deb -n tinygo -a $(DEB_ARCH) -v $(shell grep "const Version = " goenv/version.go | awk '{print $$NF}') -m '@tinygo-org' --description='TinyGo is a Go compiler for small places.' --license='BSD 3-Clause' --url=https://tinygo.org/ --deb-changelog CHANGELOG.md -p build/release.deb -C ./build/release-deb
ifneq ($(RELEASEONLY), 1)
release: build/release
deb: build/release
endif
+4 -1
View File
@@ -43,7 +43,7 @@ See the [getting started instructions](https://tinygo.org/getting-started/) for
You can compile TinyGo programs for microcontrollers, WebAssembly and Linux.
The following 82 microcontroller boards are currently supported:
The following 85 microcontroller boards are currently supported:
* [Adafruit Circuit Playground Bluefruit](https://www.adafruit.com/product/4333)
* [Adafruit Circuit Playground Express](https://www.adafruit.com/product/3333)
@@ -85,6 +85,7 @@ The following 82 microcontroller boards are currently supported:
* [Dragino LoRaWAN GPS Tracker LGT-92](http://www.dragino.com/products/lora-lorawan-end-node/item/142-lgt-92.html)
* [ESP32 - Core board](https://www.espressif.com/en/products/socs/esp32)
* [ESP32 - mini32](https://www.espressif.com/en/products/socs/esp32)
* [ESP32-C3-12f](https://www.espressif.com/en/products/socs/esp32-c3)
* [ESP8266 - d1mini](https://www.espressif.com/en/products/socs/esp8266)
* [ESP8266 - NodeMCU](https://www.espressif.com/en/products/socs/esp8266)
* [Game Boy Advance](https://en.wikipedia.org/wiki/Game_Boy_Advance)
@@ -112,10 +113,12 @@ The following 82 microcontroller boards are currently supported:
* [Raspberry Pi Pico](https://www.raspberrypi.org/products/raspberry-pi-pico/)
* [Raytac MDBT50Q-RX Dongle (with TinyUF2 bootloader)](https://www.adafruit.com/product/5199)
* [Seeed Seeeduino XIAO](https://www.seeedstudio.com/Seeeduino-XIAO-Arduino-Microcontroller-SAMD21-Cortex-M0+-p-4426.html)
* [Seeed XIAO BLE](https://www.seeedstudio.com/Seeed-XIAO-BLE-nRF52840-p-5201.html)
* [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)
* [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)
* [ST Micro "Nucleo" L031K6](https://www.st.com/ja/evaluation-tools/nucleo-l031k6.html)
+8 -1
View File
@@ -37,8 +37,14 @@ import (
// BuildResult is the output of a build. This includes the binary itself and
// some other metadata that is obtained while building the binary.
type BuildResult struct {
// The executable directly from the linker, usually including debug
// information. Used for GDB for example.
Executable string
// A path to the output binary. It will be removed after Build returns, so
// if it should be kept it must be copied or moved away.
// It is often the same as Executable, but differs if the output format is
// .hex for example (instead of the usual ELF).
Binary string
// The directory of the main package. This is useful for testing as the test
@@ -835,7 +841,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
if err != nil {
return err
}
case "esp32", "esp32c3", "esp8266":
case "esp32", "esp32-img", "esp32c3", "esp8266":
// Special format for the ESP family of chips (parsed by the ROM
// bootloader).
tmppath = filepath.Join(dir, "main"+outext)
@@ -867,6 +873,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
}
return action(BuildResult{
Executable: executable,
Binary: tmppath,
MainDir: lprogram.MainPkg().Dir,
ModuleRoot: moduleroot,
+14 -1
View File
@@ -1,7 +1,11 @@
package builder
import (
"os"
"path/filepath"
"strings"
"github.com/tinygo-org/tinygo/goenv"
)
// These are the GENERIC_SOURCES according to CMakeList.txt.
@@ -72,6 +76,7 @@ var genericBuiltins = []string{
"floatunsisf.c",
"floatuntidf.c",
"floatuntisf.c",
"fp_mode.c",
//"int_util.c",
"lshrdi3.c",
"lshrti3.c",
@@ -161,7 +166,15 @@ var CompilerRT = Library{
cflags: func(target, headerPath string) []string {
return []string{"-Werror", "-Wall", "-std=c11", "-nostdlibinc"}
},
sourceDir: "lib/compiler-rt/lib/builtins",
sourceDir: func() string {
llvmDir := filepath.Join(goenv.Get("TINYGOROOT"), "llvm-project/compiler-rt/lib/builtins")
if _, err := os.Stat(llvmDir); err == nil {
// Release build.
return llvmDir
}
// Development build.
return filepath.Join(goenv.Get("TINYGOROOT"), "lib/compiler-rt-builtins")
},
librarySources: func(target string) []string {
builtins := append([]string{}, genericBuiltins...) // copy genericBuiltins
if strings.HasPrefix(target, "arm") || strings.HasPrefix(target, "thumb") {
+3 -4
View File
@@ -38,6 +38,7 @@
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCTargetOptions.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/OptTable.h"
@@ -51,7 +52,6 @@
#include "llvm/Support/Process.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
@@ -120,7 +120,6 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
llvm::StringSwitch<llvm::DebugCompressionType>(A->getValue())
.Case("none", llvm::DebugCompressionType::None)
.Case("zlib", llvm::DebugCompressionType::Z)
.Case("zlib-gnu", llvm::DebugCompressionType::GNU)
.Default(llvm::DebugCompressionType::None);
}
@@ -382,7 +381,7 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
T, Ctx, std::move(MAB), std::move(OW), std::move(CE), *STI,
Opts.RelaxAll, Opts.IncrementalLinkerCompatible,
/*DWARFMustBeAtTheEnd*/ true));
Str.get()->InitSections(Opts.NoExecStack);
Str.get()->initSections(Opts.NoExecStack, *STI);
}
// When -fembed-bitcode is passed to clang_as, a 1-byte marker
@@ -442,7 +441,7 @@ bool ExecuteAssembler(AssemblerInvocation &Opts,
return Failed;
}
static void LLVMErrorHandler(void *UserData, const std::string &Message,
static void LLVMErrorHandler(void *UserData, const char *Message,
bool GenCrashDiag) {
DiagnosticsEngine &Diags = *static_cast<DiagnosticsEngine*>(UserData);
+2 -2
View File
@@ -33,8 +33,8 @@ func NewConfig(options *compileopts.Options) (*compileopts.Config, error) {
if err != nil {
return nil, fmt.Errorf("could not read version from GOROOT (%v): %v", goroot, err)
}
if major != 1 || minor < 15 || minor > 17 {
return nil, fmt.Errorf("requires go version 1.15 through 1.17, got go%d.%d", major, minor)
if major != 1 || minor < 15 || minor > 18 {
return nil, fmt.Errorf("requires go version 1.15 through 1.18, got go%d.%d", major, minor)
}
clangHeaderPath := getClangHeaderPath(goenv.Get("TINYGOROOT"))
+6 -1
View File
@@ -6,6 +6,7 @@ import (
"github.com/tinygo-org/tinygo/compileopts"
"github.com/tinygo-org/tinygo/goenv"
"tinygo.org/x/go-llvm"
)
// Create a job that builds a Darwin libSystem.dylib stub library. This library
@@ -38,8 +39,12 @@ func makeDarwinLibSystemJob(config *compileopts.Config, tmpdir string) *compileJ
// Link object file to dynamic library.
platformVersion := strings.TrimPrefix(strings.Split(config.Triple(), "-")[2], "macosx")
flavor := "darwin"
if strings.Split(llvm.Version, ".")[0] < "13" {
flavor = "darwinnew" // needed on LLVM 12 and below
}
flags = []string{
"-flavor", "darwinnew",
"-flavor", flavor,
"-demangle",
"-dynamic",
"-dylib",
+30 -3
View File
@@ -15,6 +15,7 @@ import (
"fmt"
"io/ioutil"
"sort"
"strings"
)
type espImageSegment struct {
@@ -78,15 +79,31 @@ func makeESPFirmareImage(infile, outfile, format string) error {
// An added benefit is that we don't need to check for errors all the time.
outf := &bytes.Buffer{}
// Separate esp32 and esp32-img. The -img suffix indicates we should make an
// image, not just a binary to be flashed at 0x1000 for example.
chip := format
makeImage := false
if strings.HasSuffix(format, "-img") {
makeImage = true
chip = format[:len(format)-len("-img")]
}
if makeImage {
// The bootloader starts at 0x1000, or 4096.
// TinyGo doesn't use a separate bootloader and runs the entire
// application in the bootloader location.
outf.Write(make([]byte, 4096))
}
// Chip IDs. Source:
// https://github.com/espressif/esp-idf/blob/v4.3/components/bootloader_support/include/esp_app_format.h#L22
chip_id := map[string]uint16{
"esp32": 0x0000,
"esp32c3": 0x0005,
}[format]
}[chip]
// Image header.
switch format {
switch chip {
case "esp32", "esp32c3":
// Header format:
// https://github.com/espressif/esp-idf/blob/v4.3/components/bootloader_support/include/esp_app_format.h#L71
@@ -155,12 +172,22 @@ func makeESPFirmareImage(infile, outfile, format string) error {
outf.Write(make([]byte, 15-outf.Len()%16))
outf.WriteByte(checksum)
if format != "esp8266" {
if chip != "esp8266" {
// SHA256 hash (to protect against image corruption, not for security).
hash := sha256.Sum256(outf.Bytes())
outf.Write(hash[:])
}
// QEMU (or more precisely, qemu-system-xtensa from Espressif) expects the
// image to be a certain size.
if makeImage {
// Use a default image size of 4MB.
grow := 4096*1024 - outf.Len()
if grow > 0 {
outf.Write(make([]byte, grow))
}
}
// Write the image to the output file.
return ioutil.WriteFile(outfile, outf.Bytes(), 0666)
}
+13 -5
View File
@@ -24,8 +24,8 @@ type Library struct {
// cflags returns the C flags specific to this library
cflags func(target, headerPath string) []string
// The source directory, relative to TINYGOROOT.
sourceDir string
// The source directory.
sourceDir func() string
// The source files, relative to sourceDir.
librarySources func(target string) []string
@@ -153,7 +153,7 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ
}
}
if strings.HasPrefix(target, "arm") || strings.HasPrefix(target, "thumb") {
args = append(args, "-fshort-enums", "-fomit-frame-pointer", "-mfloat-abi=soft", "-fno-unwind-tables")
args = append(args, "-fshort-enums", "-fomit-frame-pointer", "-mfloat-abi=soft", "-fno-unwind-tables", "-fno-asynchronous-unwind-tables")
}
if strings.HasPrefix(target, "riscv32-") {
args = append(args, "-march=rv32imac", "-mabi=ilp32", "-fforce-enable-int128")
@@ -161,6 +161,12 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ
if strings.HasPrefix(target, "riscv64-") {
args = append(args, "-march=rv64gc", "-mabi=lp64")
}
if strings.HasPrefix(target, "xtensa") {
// Hack to work around an issue in the Xtensa port:
// https://github.com/espressif/llvm-project/issues/52
// Hopefully this will be fixed soon (LLVM 14).
args = append(args, "-D__ELF__")
}
var once sync.Once
@@ -195,6 +201,8 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ
},
}
sourceDir := l.sourceDir()
// Create jobs to compile all sources. These jobs are depended upon by the
// archive job above, so must be run first.
for _, path := range l.librarySources(target) {
@@ -203,7 +211,7 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ
for strings.HasPrefix(cleanpath, "../") {
cleanpath = cleanpath[3:]
}
srcpath := filepath.Join(goenv.Get("TINYGOROOT"), l.sourceDir, path)
srcpath := filepath.Join(sourceDir, path)
objpath := filepath.Join(dir, cleanpath+".o")
os.MkdirAll(filepath.Dir(objpath), 0o777)
objs = append(objs, objpath)
@@ -227,7 +235,7 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ
// (It could be done in parallel with creating the ar file, but it probably
// won't make much of a difference in speed).
if l.crt1Source != "" {
srcpath := filepath.Join(goenv.Get("TINYGOROOT"), l.sourceDir, l.crt1Source)
srcpath := filepath.Join(sourceDir, l.crt1Source)
job.dependencies = append(job.dependencies, &compileJob{
description: "compile " + srcpath,
run: func(*compileJob) error {
+4 -4
View File
@@ -8,22 +8,22 @@ extern "C" {
bool tinygo_link_elf(int argc, char **argv) {
std::vector<const char*> args(argv, argv + argc);
return lld::elf::link(args, false, llvm::outs(), llvm::errs());
return lld::elf::link(args, llvm::outs(), llvm::errs(), false, false);
}
bool tinygo_link_macho(int argc, char **argv) {
std::vector<const char*> args(argv, argv + argc);
return lld::macho::link(args, false, llvm::outs(), llvm::errs());
return lld::macho::link(args, llvm::outs(), llvm::errs(), false, false);
}
bool tinygo_link_mingw(int argc, char **argv) {
std::vector<const char*> args(argv, argv + argc);
return lld::mingw::link(args, false, llvm::outs(), llvm::errs());
return lld::mingw::link(args, llvm::outs(), llvm::errs(), false, false);
}
bool tinygo_link_wasm(int argc, char **argv) {
std::vector<const char*> args(argv, argv + argc);
return lld::wasm::link(args, false, llvm::outs(), llvm::errs());
return lld::wasm::link(args, llvm::outs(), llvm::errs(), false, false);
}
} // external "C"
+1
View File
@@ -26,6 +26,7 @@ var MinGW = Library{
_, err = io.Copy(outf, inf)
return err
},
sourceDir: func() string { return "" }, // unused
cflags: func(target, headerPath string) []string {
// No flags necessary because there are no files to compile.
return nil
+1 -1
View File
@@ -104,7 +104,7 @@ var Musl = Library{
"-fno-stack-protector",
}
},
sourceDir: "lib/musl/src",
sourceDir: func() string { return filepath.Join(goenv.Get("TINYGOROOT"), "lib/musl/src") },
librarySources: func(target string) []string {
arch := compileopts.MuslArchitecture(target)
globs := []string{
+1 -1
View File
@@ -33,7 +33,7 @@ var Picolibc = Library{
"-I" + headerPath,
}
},
sourceDir: "lib/picolibc/newlib/libc",
sourceDir: func() string { return filepath.Join(goenv.Get("TINYGOROOT"), "lib/picolibc/newlib/libc") },
librarySources: func(target string) []string {
return picolibcSources
},
+1 -1
View File
@@ -54,7 +54,7 @@ func RunTool(tool string, args ...string) error {
ok = C.tinygo_clang_driver(C.int(len(args)), (**C.char)(buf))
case "ld.lld":
switch linker {
case "darwinnew":
case "darwin", "darwinnew": // darwinnew is only needed for LLVM 12 and below
ok = C.tinygo_link_macho(C.int(len(args)), (**C.char)(buf))
case "elf":
ok = C.tinygo_link_elf(C.int(len(args)), (**C.char)(buf))
+2 -2
View File
@@ -1,5 +1,5 @@
//go:build !byollvm && !llvm11 && !llvm12
// +build !byollvm,!llvm11,!llvm12
//go:build !byollvm && !llvm11 && !llvm12 && !llvm14
// +build !byollvm,!llvm11,!llvm12,!llvm14
package cgo
+16
View File
@@ -0,0 +1,16 @@
//go:build !byollvm && llvm14
// +build !byollvm,llvm14
package cgo
/*
#cgo linux CFLAGS: -I/usr/lib/llvm-14/include
#cgo darwin,amd64 CFLAGS: -I/usr/local/opt/llvm@14/include
#cgo darwin,arm64 CFLAGS: -I/opt/homebrew/opt/llvm@14/include
#cgo freebsd CFLAGS: -I/usr/local/llvm14/include
#cgo linux LDFLAGS: -L/usr/lib/llvm-14/lib -lclang
#cgo darwin,amd64 LDFLAGS: -L/usr/local/opt/llvm@14/lib -lclang -lffi
#cgo darwin,arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@14/lib -lclang -lffi
#cgo freebsd LDFLAGS: -L/usr/local/llvm14/lib -lclang
*/
import "C"
+45 -6
View File
@@ -10,6 +10,7 @@ import (
"regexp"
"strings"
"github.com/google/shlex"
"github.com/tinygo-org/tinygo/goenv"
)
@@ -287,6 +288,7 @@ func (c *Config) CFlags() []string {
path, _ := c.LibcPath("picolibc")
cflags = append(cflags,
"--sysroot="+path,
"-isystem", filepath.Join(path, "include"), // necessary for Xtensa
"-isystem", filepath.Join(picolibcDir, "include"),
"-isystem", filepath.Join(picolibcDir, "tinystdio"),
)
@@ -393,6 +395,13 @@ func (c *Config) BinaryFormat(ext string) string {
return c.Target.BinaryFormat
}
return "bin"
case ".img":
// Image file. Only defined for the ESP32 at the moment, where it is a
// full (runnable) image that can be used in the Espressif QEMU fork.
if c.Target.BinaryFormat != "" {
return c.Target.BinaryFormat + "-img"
}
return "bin"
case ".hex":
// Similar to bin, but includes the start address and is thus usually a
// better format.
@@ -493,13 +502,43 @@ func (c *Config) WasmAbi() string {
return c.Target.WasmAbi
}
// Emulator returns the emulator target config
func (c *Config) Emulator() []string {
var emulator []string
for _, s := range c.Target.Emulator {
emulator = append(emulator, strings.ReplaceAll(s, "{root}", goenv.Get("TINYGOROOT")))
// EmulatorName is a shorthand to get the command for this emulator, something
// like qemu-system-arm or simavr.
func (c *Config) EmulatorName() string {
parts := strings.SplitN(c.Target.Emulator, " ", 2)
if len(parts) > 1 {
return parts[0]
}
return emulator
return ""
}
// EmulatorFormat returns the binary format for the emulator and the associated
// file extension. An empty string means to pass directly whatever the linker
// produces directly without conversion (usually ELF format).
func (c *Config) EmulatorFormat() (format, fileExt string) {
switch {
case strings.Contains(c.Target.Emulator, "{img}"):
return "img", ".img"
default:
return "", ""
}
}
// Emulator returns a ready-to-run command to run the given binary in an
// emulator. Give it the format (returned by EmulatorFormat()) and the path to
// the compiled binary.
func (c *Config) Emulator(format, binary string) ([]string, error) {
parts, err := shlex.Split(c.Target.Emulator)
if err != nil {
return nil, fmt.Errorf("could not parse emulator command: %w", err)
}
var emulator []string
for _, s := range parts {
s = strings.ReplaceAll(s, "{root}", goenv.Get("TINYGOROOT"))
s = strings.ReplaceAll(s, "{"+format+"}", binary)
emulator = append(emulator, s)
}
return emulator, nil
}
type TestConfig struct {
+16 -22
View File
@@ -44,8 +44,8 @@ type TargetSpec struct {
LDFlags []string `json:"ldflags"`
LinkerScript string `json:"linkerscript"`
ExtraFiles []string `json:"extra-files"`
RP2040BootPatch *bool `json:"rp2040-boot-patch"` // Patch RP2040 2nd stage bootloader checksum
Emulator []string `json:"emulator" override:"copy"` // inherited Emulator must not be append
RP2040BootPatch *bool `json:"rp2040-boot-patch"` // Patch RP2040 2nd stage bootloader checksum
Emulator string `json:"emulator"`
FlashCommand string `json:"flash-command"`
GDB []string `json:"gdb"`
PortReset string `json:"flash-1200-bps-reset"`
@@ -59,6 +59,7 @@ type TargetSpec struct {
OpenOCDTarget string `json:"openocd-target"`
OpenOCDTransport string `json:"openocd-transport"`
OpenOCDCommands []string `json:"openocd-commands"`
OpenOCDVerify *bool `json:"openocd-verify"` // enable verify when flashing with openocd
JLinkDevice string `json:"jlink-device"`
CodeModel string `json:"code-model"`
RelocationModel string `json:"relocation-model"`
@@ -89,19 +90,8 @@ func (spec *TargetSpec) overrideProperties(child *TargetSpec) {
if !src.IsNil() {
dst.Set(src)
}
case reflect.Slice: // for slices...
if src.Len() > 0 { // ... if not empty ...
switch tag := field.Tag.Get("override"); tag {
case "copy":
// copy the field of child to spec
dst.Set(src)
case "append", "":
// or append the field of child to spec
dst.Set(reflect.AppendSlice(dst, src))
default:
panic("override mode must be 'copy' or 'append' (default). I don't know how to '" + tag + "'.")
}
}
case reflect.Slice: // for slices, append the field
dst.Set(reflect.AppendSlice(dst, src))
default:
panic("unknown field type : " + kind.String())
}
@@ -258,7 +248,7 @@ func defaultTarget(goos, goarch, triple string) (*TargetSpec, error) {
spec.Features = "+cx8,+fxsr,+mmx,+sse,+sse2,+x87"
case "arm":
spec.CPU = "generic"
spec.CFlags = append(spec.CFlags, "-fno-unwind-tables")
spec.CFlags = append(spec.CFlags, "-fno-unwind-tables", "-fno-asynchronous-unwind-tables")
switch strings.Split(triple, "-")[0] {
case "armv5":
spec.Features = "+armv5t,+strict-align,-aes,-bf16,-d32,-dotprod,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-mve.fp,-neon,-sha2,-thumb-mode,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp"
@@ -276,8 +266,12 @@ func defaultTarget(goos, goarch, triple string) (*TargetSpec, error) {
spec.Libc = "darwin-libSystem"
arch := strings.Split(triple, "-")[0]
platformVersion := strings.TrimPrefix(strings.Split(triple, "-")[2], "macosx")
flavor := "darwin"
if strings.Split(llvm.Version, ".")[0] < "13" {
flavor = "darwinnew" // needed on LLVM 12 and below
}
spec.LDFlags = append(spec.LDFlags,
"-flavor", "darwinnew",
"-flavor", flavor,
"-dead_strip",
"-arch", arch,
"-platform_version", "macos", platformVersion, platformVersion,
@@ -330,20 +324,20 @@ func defaultTarget(goos, goarch, triple string) (*TargetSpec, error) {
case "386":
// amd64 can _usually_ run 32-bit programs, so skip the emulator in that case.
if runtime.GOARCH != "amd64" {
spec.Emulator = []string{"qemu-i386"}
spec.Emulator = "qemu-i386 {}"
}
case "amd64":
spec.Emulator = []string{"qemu-x86_64"}
spec.Emulator = "qemu-x86_64 {}"
case "arm":
spec.Emulator = []string{"qemu-arm"}
spec.Emulator = "qemu-arm {}"
case "arm64":
spec.Emulator = []string{"qemu-aarch64"}
spec.Emulator = "qemu-aarch64 {}"
}
}
}
if goos != runtime.GOOS {
if goos == "windows" {
spec.Emulator = []string{"wine"}
spec.Emulator = "wine {}"
}
}
return &spec, nil
-5
View File
@@ -29,7 +29,6 @@ func TestOverrideProperties(t *testing.T) {
CPU: "baseCpu",
CFlags: []string{"-base-foo", "-base-bar"},
BuildTags: []string{"bt1", "bt2"},
Emulator: []string{"be1", "be2"},
DefaultStackSize: 42,
AutoStackSize: &baseAutoStackSize,
}
@@ -38,7 +37,6 @@ func TestOverrideProperties(t *testing.T) {
GOOS: "",
CPU: "chlidCpu",
CFlags: []string{"-child-foo", "-child-bar"},
Emulator: []string{"ce1", "ce2"},
AutoStackSize: &childAutoStackSize,
DefaultStackSize: 64,
}
@@ -57,9 +55,6 @@ func TestOverrideProperties(t *testing.T) {
if !reflect.DeepEqual(base.BuildTags, []string{"bt1", "bt2"}) {
t.Errorf("Overriding failed : got %v", base.BuildTags)
}
if !reflect.DeepEqual(base.Emulator, []string{"ce1", "ce2"}) {
t.Errorf("Overriding failed : got %v", base.Emulator)
}
if *base.AutoStackSize != false {
t.Errorf("Overriding failed : got %v", base.AutoStackSize)
}
+18 -6
View File
@@ -957,10 +957,10 @@ func (b *builder) createFunction() {
} else {
fieldOffsets := b.expandFormalParamOffsets(llvmType)
for i, field := range fields {
expr := b.dibuilder.CreateExpression([]int64{
0x1000, // DW_OP_LLVM_fragment
int64(fieldOffsets[i]) * 8, // offset in bits
int64(b.targetData.TypeAllocSize(field.Type())) * 8, // size in bits
expr := b.dibuilder.CreateExpression([]uint64{
0x1000, // DW_OP_LLVM_fragment
fieldOffsets[i] * 8, // offset in bits
b.targetData.TypeAllocSize(field.Type()) * 8, // size in bits
})
b.dibuilder.InsertValueAtEnd(field, dbgParam, expr, loc, entryBlock)
}
@@ -1440,7 +1440,7 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error)
return b.emitSV64Call(instr.Args)
case strings.HasPrefix(name, "(device/riscv.CSR)."):
return b.emitCSROperation(instr)
case strings.HasPrefix(name, "syscall.Syscall"):
case strings.HasPrefix(name, "syscall.Syscall") || strings.HasPrefix(name, "syscall.RawSyscall"):
return b.createSyscall(instr)
case strings.HasPrefix(name, "syscall.rawSyscallNoError"):
return b.createRawSyscallNoError(instr)
@@ -1469,6 +1469,14 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error)
case *ssa.Function:
// Regular function call. No context is necessary.
context = llvm.Undef(b.i8ptrType)
if info.variadic && len(fn.Params) == 0 {
// This matches Clang, see: https://godbolt.org/z/Gqv49xKMq
// Eventually we might be able to eliminate this special case
// entirely. For details, see:
// https://discourse.llvm.org/t/rfc-enabling-wstrict-prototypes-by-default-in-c/60521
fnType := llvm.FunctionType(callee.Type().ElementType().ReturnType(), nil, false)
callee = llvm.ConstBitCast(callee, llvm.PointerType(fnType, b.funcPtrAddrSpace))
}
case *ssa.MakeClosure:
// A call on a func value, but the callee is trivial to find. For
// example: immediately applied functions.
@@ -1554,7 +1562,11 @@ func (c *compilerContext) maxSliceSize(elementType llvm.Type) uint64 {
// Determine the maximum allowed size for a slice. The biggest possible
// pointer (starting from 0) would be maxPointerValue*sizeof(elementType) so
// divide by the element type to get the real maximum size.
maxSize := maxPointerValue / c.targetData.TypeAllocSize(elementType)
elementSize := c.targetData.TypeAllocSize(elementType)
if elementSize == 0 {
elementSize = 1
}
maxSize := maxPointerValue / elementSize
// len(slice) is an int. Make sure the length remains small enough to fit in
// an int.
+2 -2
View File
@@ -226,9 +226,9 @@ func filterIrrelevantIRLines(lines []string) []string {
// Right now test outputs are for LLVM 12 and higher.
continue
}
if llvmVersion < 13 && strings.HasPrefix(line, "target datalayout = ") {
if llvmVersion < 14 && strings.HasPrefix(line, "target datalayout = ") {
// The datalayout string may vary betewen LLVM versions.
// Right now test outputs are for LLVM 13 and higher.
// Right now test outputs are for LLVM 14 and higher.
continue
}
out = append(out, line)
+4 -1
View File
@@ -98,7 +98,10 @@ func (b *builder) createInlineAsmFull(instr *ssa.CallCommon) (llvm.Value, error)
case llvm.IntegerTypeKind:
constraints = append(constraints, "r")
case llvm.PointerTypeKind:
constraints = append(constraints, "*m")
// Memory references require a type in LLVM 14, probably as a
// preparation for opaque pointers.
err = b.makeError(instr.Pos(), "support for pointer operands was dropped in TinyGo 0.23")
return s
default:
err = b.makeError(instr.Pos(), "unknown type in inline assembly for value: "+name)
return s
+79 -45
View File
@@ -152,6 +152,27 @@ func (c *compilerContext) makeStructTypeFields(typ *types.Struct) llvm.Value {
return structGlobal
}
var basicTypes = [...]string{
types.Bool: "bool",
types.Int: "int",
types.Int8: "int8",
types.Int16: "int16",
types.Int32: "int32",
types.Int64: "int64",
types.Uint: "uint",
types.Uint8: "uint8",
types.Uint16: "uint16",
types.Uint32: "uint32",
types.Uint64: "uint64",
types.Uintptr: "uintptr",
types.Float32: "float32",
types.Float64: "float64",
types.Complex64: "complex64",
types.Complex128: "complex128",
types.String: "string",
types.UnsafePointer: "unsafe.Pointer",
}
// getTypeCodeName returns a name for this type that can be used in the
// interface lowering pass to assign type codes as expected by the reflect
// package. See getTypeCodeNum.
@@ -162,48 +183,7 @@ func getTypeCodeName(t types.Type) string {
case *types.Array:
return "array:" + strconv.FormatInt(t.Len(), 10) + ":" + getTypeCodeName(t.Elem())
case *types.Basic:
var kind string
switch t.Kind() {
case types.Bool:
kind = "bool"
case types.Int:
kind = "int"
case types.Int8:
kind = "int8"
case types.Int16:
kind = "int16"
case types.Int32:
kind = "int32"
case types.Int64:
kind = "int64"
case types.Uint:
kind = "uint"
case types.Uint8:
kind = "uint8"
case types.Uint16:
kind = "uint16"
case types.Uint32:
kind = "uint32"
case types.Uint64:
kind = "uint64"
case types.Uintptr:
kind = "uintptr"
case types.Float32:
kind = "float32"
case types.Float64:
kind = "float64"
case types.Complex64:
kind = "complex64"
case types.Complex128:
kind = "complex128"
case types.String:
kind = "string"
case types.UnsafePointer:
kind = "unsafeptr"
default:
panic("unknown basic type: " + t.Name())
}
return "basic:" + kind
return "basic:" + basicTypes[t.Kind()]
case *types.Chan:
return "chan:" + getTypeCodeName(t.Elem())
case *types.Interface:
@@ -591,23 +571,77 @@ func signature(sig *types.Signature) string {
if i > 0 {
s += ", "
}
s += sig.Params().At(i).Type().String()
s += typestring(sig.Params().At(i).Type())
}
s += ")"
}
if sig.Results().Len() == 0 {
// keep as-is
} else if sig.Results().Len() == 1 {
s += " " + sig.Results().At(0).Type().String()
s += " " + typestring(sig.Results().At(0).Type())
} else {
s += " ("
for i := 0; i < sig.Results().Len(); i++ {
if i > 0 {
s += ", "
}
s += sig.Results().At(i).Type().String()
s += typestring(sig.Results().At(i).Type())
}
s += ")"
}
return s
}
// typestring returns a stable (human-readable) type string for the given type
// that can be used for interface equality checks. It is almost (but not
// exactly) the same as calling t.String(). The main difference is some
// normalization around `byte` vs `uint8` for example.
func typestring(t types.Type) string {
// See: https://github.com/golang/go/blob/master/src/go/types/typestring.go
switch t := t.(type) {
case *types.Array:
return "[" + strconv.FormatInt(t.Len(), 10) + "]" + typestring(t.Elem())
case *types.Basic:
return basicTypes[t.Kind()]
case *types.Chan:
switch t.Dir() {
case types.SendRecv:
return "chan (" + typestring(t.Elem()) + ")"
case types.SendOnly:
return "chan<- (" + typestring(t.Elem()) + ")"
case types.RecvOnly:
return "<-chan (" + typestring(t.Elem()) + ")"
default:
panic("unknown channel direction")
}
case *types.Interface:
methods := make([]string, t.NumMethods())
for i := range methods {
method := t.Method(i)
methods[i] = method.Name() + signature(method.Type().(*types.Signature))
}
return "interface{" + strings.Join(methods, ";") + "}"
case *types.Map:
return "map[" + typestring(t.Key()) + "]" + typestring(t.Elem())
case *types.Named:
return t.String()
case *types.Pointer:
return "*" + typestring(t.Elem())
case *types.Signature:
return "func" + signature(t)
case *types.Slice:
return "[]" + typestring(t.Elem())
case *types.Struct:
fields := make([]string, t.NumFields())
for i := range fields {
field := t.Field(i)
fields[i] = field.Name() + " " + typestring(field.Type())
if tag := t.Tag(i); tag != "" {
fields[i] += " " + strconv.Quote(tag)
}
}
return "struct{" + strings.Join(fields, ";") + "}"
default:
panic("unknown type: " + t.String())
}
}
+1 -1
View File
@@ -31,7 +31,7 @@ func (c *checker) checkType(t llvm.Type, checked map[llvm.Type]struct{}, special
return fmt.Errorf("type %q uses global context", t.String())
default:
// we used some other context by accident
return fmt.Errorf("type %q uses context %v instead of the main context %v", t.Context(), c.ctx)
return fmt.Errorf("type %q uses context %v instead of the main context %v", t.String(), t.Context(), c.ctx)
}
// if this is a composite type, check the components of the type
+13 -1
View File
@@ -10,6 +10,13 @@ import (
"tinygo.org/x/go-llvm"
)
// constants for hashmap algorithms; must match src/runtime/hashmap.go
const (
hashmapAlgorithmBinary = iota
hashmapAlgorithmString
hashmapAlgorithmInterface
)
// createMakeMap creates a new map object (runtime.hashmap) by allocating and
// initializing an appropriately sized object.
func (b *builder) createMakeMap(expr *ssa.MakeMap) (llvm.Value, error) {
@@ -17,22 +24,27 @@ func (b *builder) createMakeMap(expr *ssa.MakeMap) (llvm.Value, error) {
keyType := mapType.Key().Underlying()
llvmValueType := b.getLLVMType(mapType.Elem().Underlying())
var llvmKeyType llvm.Type
var alg uint64 // must match values in src/runtime/hashmap.go
if t, ok := keyType.(*types.Basic); ok && t.Info()&types.IsString != 0 {
// String keys.
llvmKeyType = b.getLLVMType(keyType)
alg = hashmapAlgorithmString
} else if hashmapIsBinaryKey(keyType) {
// Trivially comparable keys.
llvmKeyType = b.getLLVMType(keyType)
alg = hashmapAlgorithmBinary
} else {
// All other keys. Implemented as map[interface{}]valueType for ease of
// implementation.
llvmKeyType = b.getLLVMRuntimeType("_interface")
alg = hashmapAlgorithmInterface
}
keySize := b.targetData.TypeAllocSize(llvmKeyType)
valueSize := b.targetData.TypeAllocSize(llvmValueType)
llvmKeySize := llvm.ConstInt(b.ctx.Int8Type(), keySize, false)
llvmValueSize := llvm.ConstInt(b.ctx.Int8Type(), valueSize, false)
sizeHint := llvm.ConstInt(b.uintptrType, 8, false)
algEnum := llvm.ConstInt(b.ctx.Int8Type(), alg, false)
if expr.Reserve != nil {
sizeHint = b.getValue(expr.Reserve)
var err error
@@ -41,7 +53,7 @@ func (b *builder) createMakeMap(expr *ssa.MakeMap) (llvm.Value, error) {
return llvm.Value{}, err
}
}
hashmap := b.createRuntimeCall("hashmapMake", []llvm.Value{llvmKeySize, llvmValueSize, sizeHint}, "")
hashmap := b.createRuntimeCall("hashmapMake", []llvm.Value{llvmKeySize, llvmValueSize, sizeHint, algEnum}, "")
return hashmap, nil
}
+1 -1
View File
@@ -1,6 +1,6 @@
; ModuleID = 'basic.go'
source_filename = "basic.go"
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128-ni:1:10:20"
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
target triple = "wasm32-unknown-wasi"
%main.kv = type { float }
+1 -1
View File
@@ -1,6 +1,6 @@
; ModuleID = 'channel.go'
source_filename = "channel.go"
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128-ni:1:10:20"
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
target triple = "wasm32-unknown-wasi"
%runtime.channel = type { i32, i32, i8, %runtime.channelBlockedList*, i32, i32, i32, i8* }
+1 -1
View File
@@ -1,6 +1,6 @@
; ModuleID = 'float.go'
source_filename = "float.go"
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128-ni:1:10:20"
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
target triple = "wasm32-unknown-wasi"
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*)
+1 -1
View File
@@ -1,6 +1,6 @@
; ModuleID = 'func.go'
source_filename = "func.go"
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128-ni:1:10:20"
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
target triple = "wasm32-unknown-wasi"
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*)
+1 -1
View File
@@ -1,6 +1,6 @@
; ModuleID = 'gc.go'
source_filename = "gc.go"
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128-ni:1:10:20"
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
target triple = "wasm32-unknown-wasi"
%runtime.typecodeID = type { %runtime.typecodeID*, i32, %runtime.interfaceMethodInfo*, %runtime.typecodeID*, i32 }
+1 -1
View File
@@ -1,6 +1,6 @@
; ModuleID = 'go1.17.go'
source_filename = "go1.17.go"
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128-ni:1:10:20"
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
target triple = "wasm32-unknown-wasi"
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*)
+1 -1
View File
@@ -1,6 +1,6 @@
; ModuleID = 'goroutine.go'
source_filename = "goroutine.go"
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128-ni:1:10:20"
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
target triple = "wasm32-unknown-wasi"
%runtime.channel = type { i32, i32, i8, %runtime.channelBlockedList*, i32, i32, i32, i8* }
+2 -2
View File
@@ -1,6 +1,6 @@
; ModuleID = 'interface.go'
source_filename = "interface.go"
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128-ni:1:10:20"
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
target triple = "wasm32-unknown-wasi"
%runtime.typecodeID = type { %runtime.typecodeID*, i32, %runtime.interfaceMethodInfo*, %runtime.typecodeID*, i32 }
@@ -128,5 +128,5 @@ declare %runtime._string @"interface:{Error:func:{}{basic:string}}.Error$invoke"
attributes #0 = { nounwind }
attributes #1 = { "tinygo-methods"="reflect/methods.Error() string" }
attributes #2 = { "tinygo-methods"="reflect/methods.String() string" }
attributes #3 = { "tinygo-invoke"="main.$methods.foo(int) byte" "tinygo-methods"="reflect/methods.String() string; main.$methods.foo(int) byte" }
attributes #3 = { "tinygo-invoke"="main.$methods.foo(int) uint8" "tinygo-methods"="reflect/methods.String() string; main.$methods.foo(int) uint8" }
attributes #4 = { "tinygo-invoke"="reflect/methods.Error() string" "tinygo-methods"="reflect/methods.Error() string" }
+1 -1
View File
@@ -1,6 +1,6 @@
; ModuleID = 'intrinsics.go'
source_filename = "intrinsics.go"
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128-ni:1:10:20"
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
target triple = "wasm32-unknown-wasi"
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*)
+1 -1
View File
@@ -1,6 +1,6 @@
; ModuleID = 'pointer.go'
source_filename = "pointer.go"
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128-ni:1:10:20"
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
target triple = "wasm32-unknown-wasi"
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*)
+1 -1
View File
@@ -1,6 +1,6 @@
; ModuleID = 'pragma.go'
source_filename = "pragma.go"
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128-ni:1:10:20"
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
target triple = "wasm32-unknown-wasi"
@extern_global = external global [0 x i8], align 1
+1 -1
View File
@@ -1,6 +1,6 @@
; ModuleID = 'slice.go'
source_filename = "slice.go"
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128-ni:1:10:20"
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
target triple = "wasm32-unknown-wasi"
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*)
+1 -1
View File
@@ -1,6 +1,6 @@
; ModuleID = 'string.go'
source_filename = "string.go"
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128-ni:1:10:20"
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
target triple = "wasm32-unknown-wasi"
%runtime._string = type { i8*, i32 }
+1 -1
View File
@@ -15,5 +15,5 @@ require (
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9
golang.org/x/tools v0.1.6-0.20210813165731-45389f592fe9
gopkg.in/yaml.v2 v2.4.0
tinygo.org/x/go-llvm v0.0.0-20220211075103-ee4aad45c3a1
tinygo.org/x/go-llvm v0.0.0-20220420140351-512c94c1e71f
)
+2 -2
View File
@@ -80,5 +80,5 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
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=
tinygo.org/x/go-llvm v0.0.0-20220211075103-ee4aad45c3a1 h1:6G8AxueDdqobCEqQrmHPLaEH1AZ1p6Y7rGElDNT7N98=
tinygo.org/x/go-llvm v0.0.0-20220211075103-ee4aad45c3a1/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
tinygo.org/x/go-llvm v0.0.0-20220420140351-512c94c1e71f h1:9/J+NpFTpAhYcbh1mC4dr9W/aAPnwrUh8dmq21xWdSM=
tinygo.org/x/go-llvm v0.0.0-20220420140351-512c94c1e71f/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
+3 -3
View File
@@ -12,7 +12,7 @@ import (
// Version of TinyGo.
// Update this value before release of new version of software.
const Version = "0.23.0-dev"
const Version = "0.23.0"
var (
// This variable is set at build time using -ldflags parameters.
@@ -58,9 +58,9 @@ func GorootVersionString(goroot string) (string, error) {
return string(data), nil
} else if data, err := ioutil.ReadFile(filepath.Join(
goroot, "src", "runtime", "internal", "sys", "zversion.go")); err == nil {
goroot, "src", "internal", "buildcfg", "zbootstrap.go")); err == nil {
r := regexp.MustCompile("const TheVersion = `(.*)`")
r := regexp.MustCompile("const version = `(.*)`")
matches := r.FindSubmatch(data)
if len(matches) != 2 {
return "", errors.New("Invalid go version output:\n" + string(data))
+1 -4
View File
@@ -1,8 +1,6 @@
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64--linux"
@"main$alloc.1" = internal unnamed_addr constant [6 x i8] c"\05\00{\00\00\04", align 8
declare void @runtime.printuint8(i8) local_unnamed_addr
declare void @runtime.printint16(i16) local_unnamed_addr
@@ -17,7 +15,6 @@ entry:
call void @runtime.printuint8(i8 3)
call void @runtime.printuint8(i8 3)
call void @runtime.printint16(i16 5)
%int16SliceDst.val = load i16, i16* bitcast ([6 x i8]* @"main$alloc.1" to i16*), align 2
call void @runtime.printint16(i16 %int16SliceDst.val)
call void @runtime.printint16(i16 5)
ret void
}
Submodule lib/compiler-rt deleted from 5bc79797e1
+1
View File
@@ -230,6 +230,7 @@ func pathsToOverride(needsSyscallPackage bool) map[string]bool {
"device/": false,
"examples/": false,
"internal/": true,
"internal/fuzz/": false,
"internal/bytealg/": false,
"internal/reflectlite/": false,
"internal/task/": false,
+204 -140
View File
@@ -2,6 +2,7 @@ package main
import (
"bytes"
"context"
"encoding/json"
"errors"
"flag"
@@ -199,8 +200,26 @@ func Test(pkgName string, stdout, stderr io.Writer, options *compileopts.Options
return false, err
}
// Pass test flags to the test binary.
var flags []string
if testVerbose {
flags = append(flags, "-test.v")
}
if testShort {
flags = append(flags, "-test.short")
}
if testRunRegexp != "" {
flags = append(flags, "-test.run="+testRunRegexp)
}
if testBenchRegexp != "" {
flags = append(flags, "-test.bench="+testBenchRegexp)
}
if testBenchTime != "" {
flags = append(flags, "-test.benchtime="+testBenchTime)
}
passed := false
err = builder.Build(pkgName, outpath, config, func(result builder.BuildResult) error {
err = buildAndRun(pkgName, config, os.Stdout, flags, nil, 0, func(cmd *exec.Cmd, result builder.BuildResult) error {
if testCompileOnly || outpath != "" {
// Write test binary to the specified file name.
if outpath == "" {
@@ -216,27 +235,52 @@ func Test(pkgName string, stdout, stderr io.Writer, options *compileopts.Options
return nil
}
// Run the test.
config.Options.Semaphore <- struct{}{}
defer func() {
<-config.Options.Semaphore
}()
start := time.Now()
var err error
passed, err = runPackageTest(config, stdout, stderr, result, testVerbose, testShort, testRunRegexp, testBenchRegexp, testBenchTime)
if err != nil {
return err
// Tests are always run in the package directory.
cmd.Dir = result.MainDir
// Wasmtime needs a few extra flags to work.
if config.EmulatorName() == "wasmtime" {
// 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)
}
// create a new temp directory just for this run, announce it to os.TempDir() via TMPDIR
tmpdir, err := ioutil.TempDir("", "tinygotmp")
if err != nil {
return fmt.Errorf("failed to create temporary directory: %w", err)
}
args = append(args, "--dir="+tmpdir, "--env=TMPDIR="+tmpdir)
// 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.
args = append(args, cmd.Args[1:]...)
cmd.Args = append(cmd.Args[:1:1], args...)
}
// Run the test.
start := time.Now()
err = cmd.Run()
duration := time.Since(start)
// Print the result.
importPath := strings.TrimSuffix(result.ImportPath, ".test")
passed = err == nil
if passed {
fmt.Fprintf(stdout, "ok \t%s\t%.3fs\n", importPath, duration.Seconds())
} else {
fmt.Fprintf(stdout, "FAIL\t%s\t%.3fs\n", importPath, duration.Seconds())
}
return nil
if _, ok := err.(*exec.ExitError); ok {
// Binary exited with a non-zero exit code, which means the test
// failed.
return nil
}
return err
})
if err, ok := err.(loader.NoTestFilesError); ok {
fmt.Fprintf(stdout, "? \t%s\t[no test files]\n", err.ImportPath)
@@ -259,81 +303,6 @@ func dirsToModuleRoot(maindir, modroot string) []string {
return dirs
}
// runPackageTest runs a test binary that was previously built. The return
// values are whether the test passed and any errors encountered while trying to
// run the binary.
func runPackageTest(config *compileopts.Config, stdout, stderr io.Writer, result builder.BuildResult, testVerbose, testShort bool, testRunRegexp string, testBenchRegexp string, testBenchTime string) (bool, error) {
var cmd *exec.Cmd
emulator := config.Emulator()
if len(emulator) == 0 {
// Run directly.
var flags []string
if testVerbose {
flags = append(flags, "-test.v")
}
if testShort {
flags = append(flags, "-test.short")
}
if testRunRegexp != "" {
flags = append(flags, "-test.run="+testRunRegexp)
}
if testBenchRegexp != "" {
flags = append(flags, "-test.bench="+testBenchRegexp)
}
if testBenchTime != "" {
flags = append(flags, "-test.benchtime="+testBenchTime)
}
cmd = executeCommand(config.Options, result.Binary, flags...)
} else {
// Run in an emulator.
args := append(emulator[1:], result.Binary)
if emulator[0] == "wasmtime" {
// create a new temp directory just for this run, announce it to os.TempDir() via TMPDIR
tmpdir, err := ioutil.TempDir("", "tinygotmp")
if err != nil {
return false, &commandError{"failed to create temporary directory", "tinygotmp", err}
}
args = append(args, "--dir="+tmpdir, "--env=TMPDIR="+tmpdir)
// TODO: add option to not delete temp dir for debugging?
defer os.RemoveAll(tmpdir)
// allow reading from directories up to module root
for _, d := range dirsToModuleRoot(result.MainDir, result.ModuleRoot) {
args = append(args, "--dir="+d)
}
// mark end of wasmtime arguments and start of program ones: --
args = append(args, "--")
if testVerbose {
args = append(args, "-test.v")
}
if testShort {
args = append(args, "-test.short")
}
if testRunRegexp != "" {
args = append(args, "-test.run="+testRunRegexp)
}
if testBenchRegexp != "" {
args = append(args, "-test.bench="+testBenchRegexp)
}
}
cmd = executeCommand(config.Options, emulator[0], args...)
}
cmd.Dir = result.MainDir
cmd.Stdout = stdout
cmd.Stderr = stderr
err := cmd.Run()
if err != nil {
if _, ok := err.(*exec.ExitError); ok {
// Binary exited with a non-zero exit code, which means the test
// failed.
return false, nil
}
return false, &commandError{"failed to run compiled binary", result.Binary, err}
}
return true, nil
}
// Flash builds and flashes the built binary to the given serial port.
func Flash(pkgName, port string, options *compileopts.Options) error {
config, err := builder.NewConfig(options)
@@ -453,7 +422,11 @@ func Flash(pkgName, port string, options *compileopts.Options) error {
if err != nil {
return err
}
args = append(args, "-c", "program "+filepath.ToSlash(result.Binary)+" reset exit")
exit := " reset exit"
if config.Target.OpenOCDVerify != nil && *config.Target.OpenOCDVerify {
exit = " verify" + exit
}
args = append(args, "-c", "program "+filepath.ToSlash(result.Binary)+exit)
cmd := executeCommand(config.Options, "openocd", args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
@@ -510,18 +483,19 @@ func Debug(debugger, pkgName string, ocdOutput bool, options *compileopts.Option
return err
}
return builder.Build(pkgName, "", config, func(result builder.BuildResult) error {
format, fileExt := config.EmulatorFormat()
return builder.Build(pkgName, fileExt, config, func(result builder.BuildResult) error {
// Find a good way to run GDB.
gdbInterface, openocdInterface := config.Programmer()
switch gdbInterface {
case "msd", "command", "":
emulator := config.Emulator()
if len(emulator) != 0 {
if emulator[0] == "mgba" {
emulator := config.EmulatorName()
if emulator != "" {
if emulator == "mgba" {
gdbInterface = "mgba"
} else if emulator[0] == "simavr" {
} else if emulator == "simavr" {
gdbInterface = "simavr"
} else if strings.HasPrefix(emulator[0], "qemu-system-") {
} else if strings.HasPrefix(emulator, "qemu-system-") {
gdbInterface = "qemu"
} else {
// Assume QEMU as an emulator.
@@ -540,6 +514,10 @@ func Debug(debugger, pkgName string, ocdOutput bool, options *compileopts.Option
port := ""
var gdbCommands []string
var daemon *exec.Cmd
emulator, err := config.Emulator(format, result.Binary)
if err != nil {
return err
}
switch gdbInterface {
case "native":
// Run GDB directly.
@@ -589,33 +567,29 @@ func Debug(debugger, pkgName string, ocdOutput bool, options *compileopts.Option
}
case "qemu":
port = ":1234"
emulator := config.Emulator()
// Run in an emulator.
args := append(emulator[1:], result.Binary, "-s", "-S")
args := append(emulator[1:], "-s", "-S")
daemon = executeCommand(config.Options, emulator[0], args...)
daemon.Stdout = os.Stdout
daemon.Stderr = os.Stderr
case "qemu-user":
port = ":1234"
emulator := config.Emulator()
// Run in an emulator.
args := append(emulator[1:], "-g", "1234", result.Binary)
args := append(emulator[1:], "-g", "1234")
daemon = executeCommand(config.Options, emulator[0], args...)
daemon.Stdout = os.Stdout
daemon.Stderr = os.Stderr
case "mgba":
port = ":2345"
emulator := config.Emulator()
// Run in an emulator.
args := append(emulator[1:], result.Binary, "-g")
args := append(emulator[1:], "-g")
daemon = executeCommand(config.Options, emulator[0], args...)
daemon.Stdout = os.Stdout
daemon.Stderr = os.Stderr
case "simavr":
port = ":1234"
emulator := config.Emulator()
// Run in an emulator.
args := append(emulator[1:], "-g", result.Binary)
args := append(emulator[1:], "-g")
daemon = executeCommand(config.Options, emulator[0], args...)
daemon.Stdout = os.Stdout
daemon.Stderr = os.Stderr
@@ -660,7 +634,7 @@ func Debug(debugger, pkgName string, ocdOutput bool, options *compileopts.Option
// Construct and execute a gdb or lldb command.
// By default: gdb -ex run <binary>
// Exit the debugger with Ctrl-D.
params := []string{result.Binary}
params := []string{result.Executable}
switch debugger {
case "gdb":
if port != "" {
@@ -692,9 +666,9 @@ func Debug(debugger, pkgName string, ocdOutput bool, options *compileopts.Option
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Run()
err = cmd.Run()
if err != nil {
return &commandError{"failed to run " + cmdName + " with", result.Binary, err}
return &commandError{"failed to run " + cmdName + " with", result.Executable, err}
}
return nil
})
@@ -704,44 +678,134 @@ func Debug(debugger, pkgName string, ocdOutput bool, options *compileopts.Option
// the options, it will run the program directly on the host or will run it in
// an emulator. For example, -target=wasm will cause the binary to be run inside
// of a WebAssembly VM.
func Run(pkgName string, options *compileopts.Options) error {
func Run(pkgName string, options *compileopts.Options, cmdArgs []string) error {
config, err := builder.NewConfig(options)
if err != nil {
return err
}
return builder.Build(pkgName, ".elf", config, func(result builder.BuildResult) error {
emulator := config.Emulator()
if len(emulator) == 0 {
// Run directly.
cmd := executeCommand(config.Options, result.Binary)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Run()
if err != nil {
if err, ok := err.(*exec.ExitError); ok && err.Exited() {
// Workaround for QEMU which always exits with an error.
return nil
}
return &commandError{"failed to run compiled binary", result.Binary, err}
}
return nil
} else {
// Run in an emulator.
args := append(emulator[1:], result.Binary)
cmd := executeCommand(config.Options, emulator[0], args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Run()
if err != nil {
if err, ok := err.(*exec.ExitError); ok && err.Exited() {
// Workaround for QEMU which always exits with an error.
return nil
}
return &commandError{"failed to run emulator with", result.Binary, err}
}
return nil
return buildAndRun(pkgName, config, os.Stdout, cmdArgs, nil, 0, func(cmd *exec.Cmd, result builder.BuildResult) error {
return cmd.Run()
})
}
// buildAndRun builds and runs the given program, writing output to stdout and
// errors to os.Stderr. It takes care of emulators (qemu, wasmtime, etc) and
// passes command line arguments and evironment variables in a way appropriate
// for the given emulator.
func buildAndRun(pkgName string, config *compileopts.Config, stdout io.Writer, cmdArgs, environmentVars []string, timeout time.Duration, run func(cmd *exec.Cmd, result builder.BuildResult) error) error {
// Determine whether we're on a system that supports environment variables
// and command line parameters (operating systems, WASI) or not (baremetal,
// WebAssembly in the browser). If we're on a system without an environment,
// we need to pass command line arguments and environment variables through
// global variables (built into the binary directly) instead of the
// conventional way.
needsEnvInVars := config.GOOS() == "js"
for _, tag := range config.BuildTags() {
if tag == "baremetal" {
needsEnvInVars = true
}
}
var args, env []string
if needsEnvInVars {
runtimeGlobals := make(map[string]string)
if len(cmdArgs) != 0 {
runtimeGlobals["osArgs"] = strings.Join(cmdArgs, "\x00")
}
if len(environmentVars) != 0 {
runtimeGlobals["osEnv"] = strings.Join(environmentVars, "\x00")
}
if len(runtimeGlobals) != 0 {
// This sets the global variables like they would be set with
// `-ldflags="-X=runtime.osArgs=first\x00second`.
// The runtime package has two variables (osArgs and osEnv) that are
// both strings, from which the parameters and environment variables
// are read.
config.Options.GlobalValues = map[string]map[string]string{
"runtime": runtimeGlobals,
}
}
} else if config.EmulatorName() == "wasmtime" {
// Wasmtime needs some special flags to pass environment variables
// and allow reading from the current directory.
args = append(args, "--dir=.")
for _, v := range environmentVars {
args = append(args, "--env", v)
}
if len(cmdArgs) != 0 {
// mark end of wasmtime arguments and start of program ones: --
args = append(args, "--")
args = append(args, cmdArgs...)
}
} else {
// Pass environment variables and command line parameters as usual.
// This also works on qemu-aarch64 etc.
args = cmdArgs
env = environmentVars
}
format, fileExt := config.EmulatorFormat()
return builder.Build(pkgName, fileExt, config, func(result builder.BuildResult) error {
// If needed, set a timeout on the command. This is done in tests so
// they don't waste resources on a stalled test.
var ctx context.Context
if timeout != 0 {
var cancel context.CancelFunc
ctx, cancel = context.WithTimeout(context.Background(), timeout)
defer cancel()
}
// Set up the command.
var name string
if config.Target.Emulator == "" {
name = result.Binary
} else {
emulator, err := config.Emulator(format, result.Binary)
if err != nil {
return err
}
name = emulator[0]
emuArgs := append([]string(nil), emulator[1:]...)
args = append(emuArgs, args...)
}
var cmd *exec.Cmd
if ctx != nil {
cmd = exec.CommandContext(ctx, name, args...)
} else {
cmd = exec.Command(name, args...)
}
cmd.Env = env
// Configure stdout/stderr. The stdout may go to a buffer, not a real
// stdout.
cmd.Stdout = stdout
cmd.Stderr = os.Stderr
if config.EmulatorName() == "simavr" {
cmd.Stdout = nil // don't print initial load commands
cmd.Stderr = stdout
}
// If this is a test, reserve CPU time for it so that increased
// parallelism doesn't blow up memory usage. If this isn't a test but
// simply `tinygo run`, then it is practically a no-op.
config.Options.Semaphore <- struct{}{}
defer func() {
<-config.Options.Semaphore
}()
// Run binary.
if config.Options.PrintCommands != nil {
config.Options.PrintCommands(cmd.Path, cmd.Args...)
}
err := run(cmd, result)
if err != nil {
if ctx != nil && ctx.Err() == context.DeadlineExceeded {
stdout.Write([]byte(fmt.Sprintf("--- timeout of %s exceeded, terminating...\n", timeout)))
err = ctx.Err()
}
return &commandError{"failed to run compiled binary", result.Binary, err}
}
return nil
})
}
@@ -1407,13 +1471,13 @@ func main() {
handleCompilerError(err)
}
case "run":
if flag.NArg() != 1 {
if flag.NArg() < 1 {
fmt.Fprintln(os.Stderr, "No package specified.")
usage(command)
os.Exit(1)
}
pkgName := filepath.ToSlash(flag.Arg(0))
err := Run(pkgName, options)
err := Run(pkgName, options, flag.Args()[1:])
handleCompilerError(err)
case "test":
var pkgNames []string
@@ -1509,7 +1573,7 @@ func main() {
os.Exit(1)
return
}
if spec.FlashMethod == "" && spec.FlashCommand == "" && spec.Emulator == nil {
if spec.FlashMethod == "" && spec.FlashCommand == "" && spec.Emulator == "" {
// This doesn't look like a regular target file, but rather like
// a parent target (such as targets/cortex-m.json).
continue
+15 -103
View File
@@ -6,7 +6,6 @@ package main
import (
"bufio"
"bytes"
"context"
"errors"
"flag"
"fmt"
@@ -14,7 +13,6 @@ import (
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"regexp"
"runtime"
"strings"
@@ -66,7 +64,6 @@ func TestBuild(t *testing.T) {
"stdlib.go",
"string.go",
"structs.go",
"testing.go",
"zeroalloc.go",
}
_, minor, err := goenv.GetGorootVersion(goenv.Get("GOROOT"))
@@ -76,6 +73,11 @@ func TestBuild(t *testing.T) {
if minor >= 17 {
tests = append(tests, "go1.17.go")
}
if minor >= 18 {
tests = append(tests, "testing_go118.go")
} else {
tests = append(tests, "testing.go")
}
if *testTarget != "" {
// This makes it possible to run one specific test (instead of all),
@@ -221,7 +223,7 @@ func runPlatTests(options compileopts.Options, tests []string, t *testing.T) {
runTest(name, options, t, nil, nil)
})
}
if len(spec.Emulator) == 0 || spec.Emulator[0] != "simavr" {
if !strings.HasPrefix(spec.Emulator, "simavr ") {
t.Run("env.go", func(t *testing.T) {
t.Parallel()
runTest("env.go", options, t, []string{"first", "second"}, []string{"ENV1=VALUE1", "ENV2=VALUE2"})
@@ -255,8 +257,8 @@ func emuCheck(t *testing.T, options compileopts.Options) {
if err != nil {
t.Fatal("failed to load target spec:", err)
}
if len(spec.Emulator) != 0 {
_, err := exec.LookPath(spec.Emulator[0])
if spec.Emulator != "" {
_, err := exec.LookPath(strings.SplitN(spec.Emulator, " ", 2)[0])
if err != nil {
if errors.Is(err, exec.ErrNotFound) {
t.Skipf("emulator not installed: %q", spec.Emulator[0])
@@ -320,117 +322,27 @@ func runTestWithConfig(name string, t *testing.T, options compileopts.Options, c
t.Fatal("could not read expected output file:", err)
}
// Create a temporary directory for test output files.
tmpdir := t.TempDir()
// Determine whether we're on a system that supports environment variables
// and command line parameters (operating systems, WASI) or not (baremetal,
// WebAssembly in the browser). If we're on a system without an environment,
// we need to pass command line arguments and environment variables through
// global variables (built into the binary directly) instead of the
// conventional way.
spec, err := compileopts.LoadTarget(&options)
config, err := builder.NewConfig(&options)
if err != nil {
t.Fatal("failed to load target spec:", err)
}
needsEnvInVars := spec.GOOS == "js"
for _, tag := range spec.BuildTags {
if tag == "baremetal" {
needsEnvInVars = true
}
}
if needsEnvInVars {
runtimeGlobals := make(map[string]string)
if len(cmdArgs) != 0 {
runtimeGlobals["osArgs"] = strings.Join(cmdArgs, "\x00")
}
if len(environmentVars) != 0 {
runtimeGlobals["osEnv"] = strings.Join(environmentVars, "\x00")
}
if len(runtimeGlobals) != 0 {
// This sets the global variables like they would be set with
// `-ldflags="-X=runtime.osArgs=first\x00second`.
// The runtime package has two variables (osArgs and osEnv) that are
// both strings, from which the parameters and environment variables
// are read.
options.GlobalValues = map[string]map[string]string{
"runtime": runtimeGlobals,
}
}
t.Fatal(err)
}
// Build the test binary.
binary := filepath.Join(tmpdir, "test")
if spec.GOOS == "windows" {
binary += ".exe"
}
err = Build("./"+path, binary, &options)
stdout := &bytes.Buffer{}
err = buildAndRun("./"+path, config, stdout, cmdArgs, environmentVars, time.Minute, func(cmd *exec.Cmd, result builder.BuildResult) error {
return cmd.Run()
})
if err != nil {
printCompilerError(t.Log, err)
t.Fail()
return
}
// Reserve CPU time for the test to run.
// This attempts to ensure that the test is not CPU-starved.
options.Semaphore <- struct{}{}
defer func() { <-options.Semaphore }()
// Create the test command, taking care of emulators etc.
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()
var cmd *exec.Cmd
// make sure any special vars in the emulator definition are rewritten
config := compileopts.Config{Target: spec}
emulator := config.Emulator()
if len(emulator) == 0 {
cmd = exec.CommandContext(ctx, binary)
} else {
args := append(emulator[1:], binary)
cmd = exec.CommandContext(ctx, emulator[0], args...)
}
if len(emulator) != 0 && emulator[0] == "wasmtime" {
// Allow reading from the current directory.
cmd.Args = append(cmd.Args, "--dir=.")
for _, v := range environmentVars {
cmd.Args = append(cmd.Args, "--env", v)
}
cmd.Args = append(cmd.Args, cmdArgs...)
} else {
if !needsEnvInVars {
cmd.Args = append(cmd.Args, cmdArgs...) // works on qemu-aarch64 etc
cmd.Env = append(cmd.Env, environmentVars...)
}
}
// Run the test.
stdout := &bytes.Buffer{}
if len(emulator) != 0 && emulator[0] == "simavr" {
cmd.Stdout = os.Stderr
cmd.Stderr = stdout
} else {
cmd.Stdout = stdout
cmd.Stderr = os.Stderr
}
err = cmd.Start()
if err != nil {
t.Fatal("failed to start:", err)
}
err = cmd.Wait()
if cerr := ctx.Err(); cerr == context.DeadlineExceeded {
stdout.WriteString("--- test ran too long, terminating...\n")
err = cerr
}
// putchar() prints CRLF, convert it to LF.
actual := bytes.Replace(stdout.Bytes(), []byte{'\r', '\n'}, []byte{'\n'}, -1)
expected = bytes.Replace(expected, []byte{'\r', '\n'}, []byte{'\n'}, -1) // for Windows
if len(emulator) != 0 && emulator[0] == "simavr" {
if config.EmulatorName() == "simavr" {
// Strip simavr log formatting.
actual = bytes.Replace(actual, []byte{0x1b, '[', '3', '2', 'm'}, nil, -1)
actual = bytes.Replace(actual, []byte{0x1b, '[', '0', 'm'}, nil, -1)
+21 -47
View File
@@ -142,18 +142,14 @@ func (mpu *MPU_Type) Enable(enable bool) {
if enable {
mpu.CTRL.Set(MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_ENABLE_Msk)
SystemControl.SHCSR.SetBits(SCB_SHCSR_MEMFAULTENA_Msk)
arm.AsmFull(`
dsb 0xF
isb 0xF
`, nil)
arm.Asm("dsb 0xF")
arm.Asm("isb 0xF")
enableDcache(true)
enableIcache(true)
} else {
enableIcache(false)
enableDcache(false)
arm.AsmFull(`
dmb 0xF
`, nil)
arm.Asm("dmb 0xF")
SystemControl.SHCSR.ClearBits(SCB_SHCSR_MEMFAULTENA_Msk)
mpu.CTRL.ClearBits(MPU_CTRL_ENABLE_Msk)
}
@@ -188,31 +184,21 @@ func (mpu *MPU_Type) SetRASR(size RegionSize, access AccessPerms, ext Extension,
func enableIcache(enable bool) {
if enable != SystemControl.CCR.HasBits(SCB_CCR_IC_Msk) {
if enable {
arm.AsmFull(`
dsb 0xF
isb 0xF
`, nil)
arm.Asm("dsb 0xF")
arm.Asm("isb 0xF")
SystemControl.ICIALLU.Set(0)
arm.AsmFull(`
dsb 0xF
isb 0xF
`, nil)
arm.Asm("dsb 0xF")
arm.Asm("isb 0xF")
SystemControl.CCR.SetBits(SCB_CCR_IC_Msk)
arm.AsmFull(`
dsb 0xF
isb 0xF
`, nil)
arm.Asm("dsb 0xF")
arm.Asm("isb 0xF")
} else {
arm.AsmFull(`
dsb 0xF
isb 0xF
`, nil)
arm.Asm("dsb 0xF")
arm.Asm("isb 0xF")
SystemControl.CCR.ClearBits(SCB_CCR_IC_Msk)
SystemControl.ICIALLU.Set(0)
arm.AsmFull(`
dsb 0xF
isb 0xF
`, nil)
arm.Asm("dsb 0xF")
arm.Asm("isb 0xF")
}
}
}
@@ -227,9 +213,7 @@ func enableDcache(enable bool) {
if enable != SystemControl.CCR.HasBits(SCB_CCR_DC_Msk) {
if enable {
SystemControl.CSSELR.Set(0)
arm.AsmFull(`
dsb 0xF
`, nil)
arm.Asm("dsb 0xF")
ccsidr := SystemControl.CCSIDR.Get()
sets := (ccsidr & SCB_CCSIDR_NUMSETS_Msk) >> SCB_CCSIDR_NUMSETS_Pos
for sets != 0 {
@@ -242,23 +226,15 @@ func enableDcache(enable bool) {
}
sets--
}
arm.AsmFull(`
dsb 0xF
`, nil)
arm.Asm("dsb 0xF")
SystemControl.CCR.SetBits(SCB_CCR_DC_Msk)
arm.AsmFull(`
dsb 0xF
isb 0xF
`, nil)
arm.Asm("dsb 0xF")
arm.Asm("isb 0xF")
} else {
SystemControl.CSSELR.Set(0)
arm.AsmFull(`
dsb 0xF
`, nil)
arm.Asm("dsb 0xF")
SystemControl.CCR.ClearBits(SCB_CCR_DC_Msk)
arm.AsmFull(`
dsb 0xF
`, nil)
arm.Asm("dsb 0xF")
dcacheCcsidr.Set(SystemControl.CCSIDR.Get())
dcacheSets.Set((dcacheCcsidr.Get() & SCB_CCSIDR_NUMSETS_Msk) >> SCB_CCSIDR_NUMSETS_Pos)
for dcacheSets.Get() != 0 {
@@ -271,10 +247,8 @@ func enableDcache(enable bool) {
}
dcacheSets.Set(dcacheSets.Get() - 1)
}
arm.AsmFull(`
dsb 0xF
isb 0xF
`, nil)
arm.Asm("dsb 0xF")
arm.Asm("isb 0xF")
}
}
}
+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)
}
}
+133
View File
@@ -0,0 +1,133 @@
// Package fuzz is a shim to allow compilation against Go 1.18.
// It only defines a single type to work with testing/internal/testdeps,
// and hide all the other new dependencies from this package.
package fuzz
import (
"context"
"errors"
"io"
"reflect"
"time"
)
// CorpusEntry represents an individual input for fuzzing.
//
// We must use an equivalent type in the testing and testing/internal/testdeps
// packages, but testing can't import this package directly, and we don't want
// to export this type from testing. Instead, we use the same struct type and
// use a type alias (not a defined type) for convenience.
type CorpusEntry = struct {
Parent string
// Path is the path of the corpus file, if the entry was loaded from disk.
// For other entries, including seed values provided by f.Add, Path is the
// name of the test, e.g. seed#0 or its hash.
Path string
// Data is the raw input data. Data should only be populated for seed
// values. For on-disk corpus files, Data will be nil, as it will be loaded
// from disk using Path.
Data []byte
// Values is the unmarshaled values from a corpus file.
Values []any
Generation int
// IsSeed indicates whether this entry is part of the seed corpus.
IsSeed bool
}
// CoordinateFuzzingOpts is a set of arguments for CoordinateFuzzing.
// The zero value is valid for each field unless specified otherwise.
type CoordinateFuzzingOpts struct {
// Log is a writer for logging progress messages and warnings.
// If nil, io.Discard will be used instead.
Log io.Writer
// Timeout is the amount of wall clock time to spend fuzzing after the corpus
// has loaded. If zero, there will be no time limit.
Timeout time.Duration
// Limit is the number of random values to generate and test. If zero,
// there will be no limit on the number of generated values.
Limit int64
// MinimizeTimeout is the amount of wall clock time to spend minimizing
// after discovering a crasher. If zero, there will be no time limit. If
// MinimizeTimeout and MinimizeLimit are both zero, then minimization will
// be disabled.
MinimizeTimeout time.Duration
// MinimizeLimit is the maximum number of calls to the fuzz function to be
// made while minimizing after finding a crash. If zero, there will be no
// limit. Calls to the fuzz function made when minimizing also count toward
// Limit. If MinimizeTimeout and MinimizeLimit are both zero, then
// minimization will be disabled.
MinimizeLimit int64
// parallel is the number of worker processes to run in parallel. If zero,
// CoordinateFuzzing will run GOMAXPROCS workers.
Parallel int
// Seed is a list of seed values added by the fuzz target with testing.F.Add
// and in testdata.
Seed []CorpusEntry
// Types is the list of types which make up a corpus entry.
// Types must be set and must match values in Seed.
Types []reflect.Type
// CorpusDir is a directory where files containing values that crash the
// code being tested may be written. CorpusDir must be set.
CorpusDir string
// CacheDir is a directory containing additional "interesting" values.
// The fuzzer may derive new values from these, and may write new values here.
CacheDir string
}
// CoordinateFuzzing creates several worker processes and communicates with
// them to test random inputs that could trigger crashes and expose bugs.
// The worker processes run the same binary in the same directory with the
// same environment variables as the coordinator process. Workers also run
// with the same arguments as the coordinator, except with the -test.fuzzworker
// flag prepended to the argument list.
//
// If a crash occurs, the function will return an error containing information
// about the crash, which can be reported to the user.
func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err error) {
return errors.New("not implemented")
}
// ReadCorpus reads the corpus from the provided dir. The returned corpus
// entries are guaranteed to match the given types. Any malformed files will
// be saved in a MalformedCorpusError and returned, along with the most recent
// error.
func ReadCorpus(dir string, types []reflect.Type) ([]CorpusEntry, error) {
return nil, errors.New("not implemented")
}
// CheckCorpus verifies that the types in vals match the expected types
// provided.
func CheckCorpus(vals []any, types []reflect.Type) error {
return errors.New("not implemented")
}
func ResetCoverage() {}
func SnapshotCoverage() {}
// RunFuzzWorker is called in a worker process to communicate with the
// coordinator process in order to fuzz random inputs. RunFuzzWorker loops
// until the coordinator tells it to stop.
//
// fn is a wrapper on the fuzz function. It may return an error to indicate
// a given input "crashed". The coordinator will also record a crasher if
// the function times out or terminates the process.
//
// RunFuzzWorker returns an error if it could not communicate with the
// coordinator process.
func RunFuzzWorker(ctx context.Context, fn func(CorpusEntry) error) error {
return errors.New("not implemented")
}
+3
View File
@@ -42,6 +42,9 @@ const (
SPIQ = IO17
U0RXD = IO20
U0TXD = IO21
UART_TX_PIN = U0TXD
UART_RX_PIN = U0RXD
)
const (
+56
View File
@@ -0,0 +1,56 @@
//go:build nrf52840 || circuitplay_bluefruit || reelboard || clue || itsybitsy_nrf52840
// +build nrf52840 circuitplay_bluefruit reelboard clue itsybitsy_nrf52840
package machine
// Hardware pins
const (
P0_00 Pin = 0
P0_01 Pin = 1
P0_02 Pin = 2
P0_03 Pin = 3
P0_04 Pin = 4
P0_05 Pin = 5
P0_06 Pin = 6
P0_07 Pin = 7
P0_08 Pin = 8
P0_09 Pin = 9
P0_10 Pin = 10
P0_11 Pin = 11
P0_12 Pin = 12
P0_13 Pin = 13
P0_14 Pin = 14
P0_15 Pin = 15
P0_16 Pin = 16
P0_17 Pin = 17
P0_18 Pin = 18
P0_19 Pin = 19
P0_20 Pin = 20
P0_21 Pin = 21
P0_22 Pin = 22
P0_23 Pin = 23
P0_24 Pin = 24
P0_25 Pin = 25
P0_26 Pin = 26
P0_27 Pin = 27
P0_28 Pin = 28
P0_29 Pin = 29
P0_30 Pin = 30
P0_31 Pin = 31
P1_00 Pin = 32
P1_01 Pin = 33
P1_02 Pin = 34
P1_03 Pin = 35
P1_04 Pin = 36
P1_05 Pin = 37
P1_06 Pin = 38
P1_07 Pin = 39
P1_08 Pin = 40
P1_09 Pin = 41
P1_10 Pin = 42
P1_11 Pin = 43
P1_12 Pin = 44
P1_13 Pin = 45
P1_14 Pin = 46
P1_15 Pin = 47
)
+66
View File
@@ -237,6 +237,8 @@ var (
}
)
// #==================================================================#
// | SPI |
// #===========#==========#===============#===========================#
// | Interface | Hardware | Clock(Freq) | SDI/SDO/SCK/CS : Alt |
// #===========#==========#===============#=================-=========#
@@ -261,6 +263,70 @@ const (
SPI3_CS_PIN = D36
)
var (
SPI0 = SPI1 // SPI0 is an alias of SPI1 (LPSPI4)
SPI1 = &_SPI1
_SPI1 = SPI{
Bus: nxp.LPSPI4,
muxSDI: muxSelect{ // D12 (PB1 [B0_01])
mux: nxp.IOMUXC_LPSPI4_SDI_SELECT_INPUT_DAISY_GPIO_B0_01_ALT3,
sel: &nxp.IOMUXC.LPSPI4_SDI_SELECT_INPUT,
},
muxSDO: muxSelect{ // D11 (PB2 [B0_02])
mux: nxp.IOMUXC_LPSPI4_SDO_SELECT_INPUT_DAISY_GPIO_B0_02_ALT3,
sel: &nxp.IOMUXC.LPSPI4_SDO_SELECT_INPUT,
},
muxSCK: muxSelect{ // D13 (PB3 [B0_03])
mux: nxp.IOMUXC_LPSPI4_SCK_SELECT_INPUT_DAISY_GPIO_B0_03_ALT3,
sel: &nxp.IOMUXC.LPSPI4_SCK_SELECT_INPUT,
},
muxCS: muxSelect{ // D10 (PB0 [B0_00])
mux: nxp.IOMUXC_LPSPI4_PCS0_SELECT_INPUT_DAISY_GPIO_B0_00_ALT3,
sel: &nxp.IOMUXC.LPSPI4_PCS0_SELECT_INPUT,
},
}
SPI2 = &_SPI2
_SPI2 = SPI{
Bus: nxp.LPSPI3,
muxSDI: muxSelect{ // D1 (PA2 [AD_B0_02])
mux: nxp.IOMUXC_LPSPI3_SDI_SELECT_INPUT_DAISY_GPIO_AD_B0_02_ALT7,
sel: &nxp.IOMUXC.LPSPI3_SDI_SELECT_INPUT,
},
muxSDO: muxSelect{ // D26 (PA30 [AD_B1_14])
mux: nxp.IOMUXC_LPSPI3_SDO_SELECT_INPUT_DAISY_GPIO_AD_B1_14_ALT2,
sel: &nxp.IOMUXC.LPSPI3_SDO_SELECT_INPUT,
},
muxSCK: muxSelect{ // D27 (PA31 [AD_B1_15])
mux: nxp.IOMUXC_LPSPI3_SCK_SELECT_INPUT_DAISY_GPIO_AD_B1_15,
sel: &nxp.IOMUXC.LPSPI3_SCK_SELECT_INPUT,
},
muxCS: muxSelect{ // D0 (PA3 [AD_B0_03])
mux: nxp.IOMUXC_LPSPI3_PCS0_SELECT_INPUT_DAISY_GPIO_AD_B0_03_ALT7,
sel: &nxp.IOMUXC.LPSPI3_PCS0_SELECT_INPUT,
},
}
SPI3 = &_SPI3
_SPI3 = SPI{
Bus: nxp.LPSPI1,
muxSDI: muxSelect{ // D34 (PC15 [SD_B0_03])
mux: nxp.IOMUXC_LPSPI1_SDI_SELECT_INPUT_DAISY_GPIO_SD_B0_03_ALT4,
sel: &nxp.IOMUXC.LPSPI1_SDI_SELECT_INPUT,
},
muxSDO: muxSelect{ // D35 (PC14 [SD_B0_02])
mux: nxp.IOMUXC_LPSPI1_SDO_SELECT_INPUT_DAISY_GPIO_SD_B0_02_ALT4,
sel: &nxp.IOMUXC.LPSPI1_SDO_SELECT_INPUT,
},
muxSCK: muxSelect{ // D37 (PC12 [SD_B0_00])
mux: nxp.IOMUXC_LPSPI1_SCK_SELECT_INPUT_DAISY_GPIO_SD_B0_00_ALT4,
sel: &nxp.IOMUXC.LPSPI1_SCK_SELECT_INPUT,
},
muxCS: muxSelect{ // D36 (PC13 [SD_B0_01])
mux: nxp.IOMUXC_LPSPI1_PCS0_SELECT_INPUT_DAISY_GPIO_SD_B0_01_ALT4,
sel: &nxp.IOMUXC.LPSPI1_PCS0_SELECT_INPUT,
},
}
)
// #====================================================#
// | I2C |
// #===========#==========#=============#===============#
+81
View File
@@ -0,0 +1,81 @@
//go:build thingplus_rp2040
// +build thingplus_rp2040
package machine
const (
LED = GPIO25
// Onboard crystal oscillator frequency, in MHz.
xoscFreq = 12 // MHz
)
// GPIO Pins
const (
GP0 Pin = GPIO0 // TX
GP1 Pin = GPIO1 // RX
GP2 Pin = GPIO2 // SCK
GP3 Pin = GPIO3 // COPI
GP4 Pin = GPIO4 // CIPO
GP6 Pin = GPIO6 // SDA
GP7 Pin = GPIO7 // SCL (connected to GPIO23 as well)
GP8 Pin = GPIO8 // WS2812 RGB LED
GP9 Pin = GPIO9 // muSDcard DATA3 / CS
GP10 Pin = GPIO10 // muSDcard DATA2
GP11 Pin = GPIO11 // muSDcard DATA1
GP12 Pin = GPIO12 // muSDcard DATA0 / CIPO
GP14 Pin = GPIO14 // muSDcard CLK /SCLK
GP15 Pin = GPIO15 // muSDcard CMD / COPI
GP16 Pin = GPIO16 // 16
GP17 Pin = GPIO17 // 17
GP18 Pin = GPIO18 // 18
GP19 Pin = GPIO19 // 19
GP20 Pin = GPIO20 // 20
GP21 Pin = GPIO21 // 21
GP22 Pin = GPIO22 // 22
GP23 Pin = GPIO23 // Connected to GPIO7
GP25 Pin = GPIO25 // Status blue LED
GP26 Pin = GPIO26 // ADC0
GP27 Pin = GPIO27 // ADC1
GP28 Pin = GPIO28 // ADC2
GP29 Pin = GPIO29 // ADC3
)
// Analog pins
const (
A0 = GPIO26
A1 = GPIO27
A2 = GPIO28
A3 = GPIO29
)
// I2C Pins.
const (
I2C0_SCL_PIN = GPIO6 // N/A
I2C0_SDA_PIN = GPIO7 // N/A
I2C1_SDA_PIN = GPIO6
I2C1_SCL_PIN = GPIO7
SDA_PIN = I2C1_SDA_PIN
SCL_PIN = I2C1_SCL_PIN
)
// SPI default pins
const (
// Default Serial Clock Bus 0 for SPI communications
SPI0_SCK_PIN = GPIO2
// 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
// Default Serial Clock Bus 1 for SPI communications to muSDcard
SPI1_SCK_PIN = GPIO14
// Default Serial Out Bus 1 for SPI communications to muSDcard
SPI1_SDO_PIN = GPIO15 // Tx
// Default Serial In Bus 1 for SPI communications to muSDcard
SPI1_SDI_PIN = GPIO12 // Rx
)
+113
View File
@@ -0,0 +1,113 @@
//go:build xiao_ble
// +build xiao_ble
// This file contains the pin mappings for the Seeed XIAO BLE nRF52840 [Sense] boards.
//
// Seeed XIAO BLE is an ultra-small size, ultra-low power Bluetooth development board based on the Nordic nRF52840.
// It features an onboard Bluetooth antenna, onboard battery charging chip, and 21*17.5mm thumb size, which makes it ideal for IoT projects.
//
// Seeed XIAO BLE nRF52840 Sense is a tiny Bluetooth LE development board designed for IoT and AI applications.
// It features an onboard antenna, 6 Dof IMU, microphone, all of which make it an ideal board to run AI using TinyML and TensorFlow Lite.
//
// SoftDevice (s140v7) is pre-flashed on this board already.
// See https://github.com/tinygo-org/bluetooth
//
// - https://www.seeedstudio.com/Seeed-XIAO-BLE-nRF52840-p-5201.html
// - https://www.seeedstudio.com/Seeed-XIAO-BLE-Sense-nRF52840-p-5253.html
//
// - https://wiki.seeedstudio.com/XIAO_BLE/
// - https://github.com/Seeed-Studio/ArduinoCore-mbed/tree/master/variants/SEEED_XIAO_NRF52840_SENSE
//
package machine
const HasLowFrequencyCrystal = true
// Digital Pins
const (
D0 Pin = P0_02
D1 Pin = P0_03
D2 Pin = P0_28
D3 Pin = P0_29
D4 Pin = P0_04
D5 Pin = P0_05
D6 Pin = P1_11
D7 Pin = P1_12
D8 Pin = P1_13
D9 Pin = P1_14
D10 Pin = P1_15
)
// Analog pins
const (
A0 Pin = P0_02
A1 Pin = P0_03
A2 Pin = P0_28
A3 Pin = P0_29
A4 Pin = P0_04
A5 Pin = P0_05
)
// Onboard LEDs
const (
LED = LED_CHG
LED1 = LED_RED
LED2 = LED_GREEN
LED3 = LED_BLUE
LED_CHG = P0_17
LED_RED = P0_26
LED_GREEN = P0_30
LED_BLUE = P0_06
)
// UART0 pins
const (
UART_RX_PIN = P1_12
UART_TX_PIN = P1_11
)
// I2C pins
const (
// Defaults to internal
SDA_PIN = SDA1_PIN
SCL_PIN = SCL1_PIN
// I2C0 (external) pins
SDA0_PIN = P0_04
SCL0_PIN = P0_05
// I2C1 (internal) pins
SDA1_PIN = P0_07
SCL1_PIN = P0_27
)
// SPI pins
const (
SPI0_SCK_PIN = P1_13
SPI0_SDO_PIN = P1_14
SPI0_SDI_PIN = P1_15
)
// Peripherals
const (
LSM_PWR = P1_08 // IMU (LSM6DS3TR) power
LSM_INT = P0_11 // IMU (LSM6DS3TR) interrupt
MIC_PWR = P1_10 // Microphone (MSM261D3526H1CPM) power
MIC_CLK = P1_00
MIC_DIN = P0_16
)
// USB CDC identifiers
const (
usb_STRING_PRODUCT = "XIAO nRF52840 Sense"
usb_STRING_MANUFACTURER = "Seeed"
)
var (
usb_VID uint16 = 0x2886
usb_PID uint16 = 0x0045
)
var (
DefaultUART = UART0
)
+257 -4
View File
@@ -5,6 +5,8 @@ package machine
import (
"device/esp"
"device/riscv"
"errors"
"runtime/interrupt"
"runtime/volatile"
"sync"
@@ -214,18 +216,269 @@ func setupPinInterrupt() error {
}).Enable()
}
var DefaultUART = UART0
var (
DefaultUART = UART0
UART0 = &_UART0
_UART0 = UART{Bus: esp.UART0, Buffer: NewRingBuffer()}
UART1 = &_UART1
_UART1 = UART{Bus: esp.UART1, Buffer: NewRingBuffer()}
onceUart = sync.Once{}
errSamePins = errors.New("UART: invalid pin combination")
errWrongUART = errors.New("UART: unsupported UARTn")
errWrongBitSize = errors.New("UART: invalid data size")
errWrongStopBitSize = errors.New("UART: invalid bit size")
)
type UART struct {
Bus *esp.UART_Type
Buffer *RingBuffer
Bus *esp.UART_Type
Buffer *RingBuffer
ParityErrorDetected bool // set when parity error detected
DataErrorDetected bool // set when data corruption detected
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
defaultParity = ParityNone
uartInterrupts = esp.UART_INT_ENA_RXFIFO_FULL_INT_ENA |
esp.UART_INT_ENA_PARITY_ERR_INT_ENA |
esp.UART_INT_ENA_FRM_ERR_INT_ENA |
esp.UART_INT_ENA_RXFIFO_OVF_INT_ENA |
esp.UART_INT_ENA_GLITCH_DET_INT_ENA
pplClockFreq = 80e6
)
type registerSet struct {
interruptMapReg *volatile.Register32
uartClockBitMask uint32
gpioMatrixSignal uint32
}
func (uart *UART) Configure(config UARTConfig) error {
if config.BaudRate == 0 {
config.BaudRate = 115200
}
if config.TX == config.RX {
return errSamePins
}
switch {
case uart.Bus == esp.UART0:
return uart.configure(config, registerSet{
interruptMapReg: &esp.INTERRUPT_CORE0.UART_INTR_MAP,
uartClockBitMask: esp.SYSTEM_PERIP_CLK_EN0_UART_CLK_EN,
gpioMatrixSignal: 6,
})
case uart.Bus == esp.UART1:
return uart.configure(config, registerSet{
interruptMapReg: &esp.INTERRUPT_CORE0.UART1_INTR_MAP,
uartClockBitMask: esp.SYSTEM_PERIP_CLK_EN0_UART1_CLK_EN,
gpioMatrixSignal: 9,
})
}
return errWrongUART
}
func (uart *UART) configure(config UARTConfig, regs registerSet) error {
initUARTClock(uart.Bus, regs)
// - disbale TX/RX clock to make sure the UART transmitter or receiver is not at work during configuration
uart.Bus.SetCLK_CONF_TX_SCLK_EN(0)
uart.Bus.SetCLK_CONF_RX_SCLK_EN(0)
// Configure static registers (Ref: Configuring URATn Communication)
// - default clock source: 1=APB_CLK, 2=FOSC_CLK, 3=XTAL_CLK
uart.Bus.SetCLK_CONF_SCLK_SEL(1)
// reset divisor of the divider via UART_SCLK_DIV_NUM, UART_SCLK_DIV_A, and UART_SCLK_DIV_B
uart.Bus.SetCLK_CONF_SCLK_DIV_NUM(0)
uart.Bus.SetCLK_CONF_SCLK_DIV_A(0)
uart.Bus.SetCLK_CONF_SCLK_DIV_B(0)
// - the baud rate
uart.SetBaudRate(config.BaudRate)
// - the data format
uart.SetFormat(defaultDataBits, defaultStopBit, defaultParity)
// - set UART mode
uart.Bus.SetRS485_CONF_RS485_EN(0)
uart.Bus.SetRS485_CONF_RS485TX_RX_EN(0)
uart.Bus.SetRS485_CONF_RS485RXBY_TX_EN(0)
uart.Bus.SetCONF0_IRDA_EN(0)
// - disable hw-flow control
uart.Bus.SetCONF0_TX_FLOW_EN(0)
uart.Bus.SetCONF1_RX_FLOW_EN(0)
// synchronize values into Core Clock
uart.Bus.SetID_REG_UPDATE(1)
uart.setupPins(config, regs)
uart.configureInterrupt(regs.interruptMapReg)
uart.enableTransmitter()
uart.enableReceiver()
// Start TX/RX
uart.Bus.SetCLK_CONF_TX_SCLK_EN(1)
uart.Bus.SetCLK_CONF_RX_SCLK_EN(1)
return nil
}
func (uart *UART) SetFormat(dataBits, stopBits int, parity UARTParity) error {
if dataBits < 5 {
return errWrongBitSize
}
if stopBits > 1 {
return errWrongStopBitSize
}
// - data length
uart.Bus.SetCONF0_BIT_NUM(uint32(dataBits - 5))
// - stop bit
uart.Bus.SetCONF0_STOP_BIT_NUM(uint32(stopBits))
// - parity check
switch parity {
case ParityNone:
uart.Bus.SetCONF0_PARITY_EN(0)
case ParityEven:
uart.Bus.SetCONF0_PARITY_EN(1)
uart.Bus.SetCONF0_PARITY(0)
case ParityOdd:
uart.Bus.SetCONF0_PARITY_EN(1)
uart.Bus.SetCONF0_PARITY(1)
}
return nil
}
func initUARTClock(bus *esp.UART_Type, regs registerSet) {
uartClock := &esp.SYSTEM.PERIP_CLK_EN0
uartClockReset := &esp.SYSTEM.PERIP_RST_EN0
// Initialize/reset URATn (Ref: Initializing URATn)
// - enable the clock for UART RAM
uartClock.SetBits(esp.SYSTEM_PERIP_CLK_EN0_UART_MEM_CLK_EN)
// - enable APB_CLK for UARTn
uartClock.SetBits(regs.uartClockBitMask)
// - reset sequence
uartClockReset.ClearBits(regs.uartClockBitMask)
bus.SetCLK_CONF_RST_CORE(1)
uartClockReset.SetBits(regs.uartClockBitMask)
uartClockReset.ClearBits(regs.uartClockBitMask)
bus.SetCLK_CONF_RST_CORE(0)
// synchronize core register
bus.SetID_REG_UPDATE(0)
// enable RTC clock
esp.RTC_CNTL.SetRTC_CLK_CONF_DIG_CLK8M_EN(1)
// wait for Core Clock to ready for configuration
for bus.GetID_REG_UPDATE() > 0 {
riscv.Asm("nop")
}
}
func (uart *UART) SetBaudRate(baudRate uint32) {
// based on esp-idf
max_div := uint32((1 << 12) - 1)
sclk_div := (pplClockFreq + (max_div * baudRate) - 1) / (max_div * baudRate)
clk_div := (pplClockFreq << 4) / (baudRate * sclk_div)
uart.Bus.SetCLKDIV(clk_div >> 4)
uart.Bus.SetCLKDIV_FRAG(clk_div & 0xf)
uart.Bus.SetCLK_CONF_SCLK_DIV_NUM(sclk_div - 1)
}
func (uart *UART) setupPins(config UARTConfig, regs registerSet) {
config.RX.Configure(PinConfig{Mode: PinInputPullup})
config.TX.Configure(PinConfig{Mode: PinInputPullup})
// link TX with GPIO signal X (technical reference manual 5.10) (this is not interrupt signal!)
config.TX.outFunc().Set(regs.gpioMatrixSignal)
// link RX with GPIO signal X and route signals via GPIO matrix (GPIO_SIGn_IN_SEL 0x40)
inFunc(regs.gpioMatrixSignal).Set(esp.GPIO_FUNC_IN_SEL_CFG_SIG_IN_SEL | uint32(config.RX))
}
func (uart *UART) configureInterrupt(intrMapReg *volatile.Register32) { // Disable all UART interrupts
// Disable all UART interrupts
uart.Bus.INT_ENA.ClearBits(0x0ffff)
intrMapReg.Set(7)
onceUart.Do(func() {
_ = interrupt.New(7, func(i interrupt.Interrupt) {
UART0.serveInterrupt(0)
UART1.serveInterrupt(1)
}).Enable()
})
}
func (uart *UART) serveInterrupt(num int) {
// get interrupt status
interrutFlag := uart.Bus.INT_ST.Get()
if (interrutFlag & uartInterrupts) == 0 {
return
}
// block UART interrupts while processing
uart.Bus.INT_ENA.ClearBits(uartInterrupts)
if interrutFlag&esp.UART_INT_ENA_RXFIFO_FULL_INT_ENA > 0 {
for uart.Bus.GetSTATUS_RXFIFO_CNT() > 0 {
b := uart.Bus.GetFIFO_RXFIFO_RD_BYTE()
if !uart.Buffer.Put(byte(b & 0xff)) {
uart.DataOverflowDetected = true
}
}
}
if interrutFlag&esp.UART_INT_ENA_PARITY_ERR_INT_ENA > 0 {
uart.ParityErrorDetected = true
}
if 0 != interrutFlag&esp.UART_INT_ENA_FRM_ERR_INT_ENA {
uart.DataErrorDetected = true
}
if 0 != interrutFlag&esp.UART_INT_ENA_RXFIFO_OVF_INT_ENA {
uart.DataOverflowDetected = true
}
if 0 != interrutFlag&esp.UART_INT_ENA_GLITCH_DET_INT_ENA {
uart.DataErrorDetected = true
}
// Clear the UART interrupt status
uart.Bus.INT_CLR.SetBits(interrutFlag)
uart.Bus.INT_CLR.ClearBits(interrutFlag)
// Enable interrupts
uart.Bus.INT_ENA.Set(uartInterrupts)
}
const uart_empty_thresh_default = 10
func (uart *UART) enableTransmitter() {
uart.Bus.SetCONF0_TXFIFO_RST(1)
uart.Bus.SetCONF0_TXFIFO_RST(0)
// TXINFO empty threshold is when txfifo_empty_int interrupt produced after the amount of data in Tx-FIFO is less than this register value.
uart.Bus.SetCONF1_TXFIFO_EMPTY_THRHD(uart_empty_thresh_default)
// we are not using interrut on TX since write we are waiting for FIFO to have space.
// uart.Bus.INT_ENA.SetBits(esp.UART_INT_ENA_TXFIFO_EMPTY_INT_ENA)
}
func (uart *UART) enableReceiver() {
uart.Bus.SetCONF0_RXFIFO_RST(1)
uart.Bus.SetCONF0_RXFIFO_RST(0)
// using value 1 so that we can start populate ring buffer with data as we get it
uart.Bus.SetCONF1_RXFIFO_FULL_THRHD(1)
// enable interrupts for:
uart.Bus.SetINT_ENA_RXFIFO_FULL_INT_ENA(1)
uart.Bus.SetINT_ENA_FRM_ERR_INT_ENA(1)
uart.Bus.SetINT_ENA_PARITY_ERR_INT_ENA(1)
uart.Bus.SetINT_ENA_GLITCH_DET_INT_ENA(1)
uart.Bus.SetINT_ENA_RXFIFO_OVF_INT_ENA(1)
}
func (uart *UART) WriteByte(b byte) error {
+4 -4
View File
@@ -236,10 +236,10 @@ func (p Pin) SetInterrupt(change PinChange, callback func(Pin)) error {
kendryte.GPIOHS.RISE_IE.ClearBits(1 << pin)
// Acknowledge interrupt atomically.
riscv.AsmFull(
"amoor.w {}, {mask}, {reg}",
"amoor.w {}, {mask}, ({reg})",
map[string]interface{}{
"mask": uint32(1 << pin),
"reg": &kendryte.GPIOHS.RISE_IP.Reg,
"reg": uintptr(unsafe.Pointer(&kendryte.GPIOHS.RISE_IP.Reg)),
})
kendryte.GPIOHS.RISE_IE.SetBits(1 << pin)
}
@@ -248,10 +248,10 @@ func (p Pin) SetInterrupt(change PinChange, callback func(Pin)) error {
kendryte.GPIOHS.FALL_IE.ClearBits(1 << pin)
// Acknowledge interrupt atomically.
riscv.AsmFull(
"amoor.w {}, {mask}, {reg}",
"amoor.w {}, {mask}, ({reg})",
map[string]interface{}{
"mask": uint32(1 << pin),
"reg": &kendryte.GPIOHS.FALL_IP.Reg,
"reg": uintptr(unsafe.Pointer(&kendryte.GPIOHS.FALL_IP.Reg)),
})
kendryte.GPIOHS.FALL_IE.SetBits(1 << pin)
}
+176
View File
@@ -883,3 +883,179 @@ func (p Pin) getMuxMode(config PinConfig) uint32 {
panic("machine: invalid pin mode")
}
}
// maximum ADC value for the currently configured resolution (used for scaling)
var adcMaximum uint32
// InitADC is not used by this machine. Use `(ADC).Configure()`.
func InitADC() {}
// Configure initializes the receiver's ADC peripheral and pin for analog input.
func (a ADC) Configure(config ADCConfig) {
// if not specified, use defaults: 10-bit resolution, 4 samples/conversion
const (
defaultResolution = uint32(10)
defaultSamples = uint32(4)
)
a.Pin.Configure(PinConfig{Mode: PinInputAnalog})
resolution, samples := config.Resolution, config.Samples
if 0 == resolution {
resolution = defaultResolution
}
if 0 == samples {
samples = defaultSamples
}
if resolution > 12 {
resolution = 12 // maximum resolution of 12 bits
}
adcMaximum = (uint32(1) << resolution) - 1
mode, average := a.mode(resolution, samples)
nxp.ADC1.CFG.Set(mode | nxp.ADC_CFG_ADHSC) // configure ADC1
nxp.ADC2.CFG.Set(mode | nxp.ADC_CFG_ADHSC) // configure ADC2
// begin calibration
nxp.ADC1.GC.Set(average | nxp.ADC_GC_CAL)
nxp.ADC2.GC.Set(average | nxp.ADC_GC_CAL)
for a.isCalibrating() {
} // wait for calibration
}
// Get performs a single ADC conversion, returning a 16-bit unsigned integer.
// The value returned will be scaled (uniformly distributed) if necessary so
// that it is always in the range [0..65535], regardless of the ADC's configured
// bit size (resolution).
func (a ADC) Get() uint16 {
if ch1, ch2, ok := a.Pin.getADCChannel(); ok {
for a.isCalibrating() {
} // wait for calibration
var val uint32
if noADCChannel != ch1 {
nxp.ADC1.HC0.Set(uint32(ch1))
for !nxp.ADC1.HS.HasBits(nxp.ADC_HS_COCO0) {
}
val = nxp.ADC1.R0.Get() & 0xFFFF
} else {
nxp.ADC2.HC0.Set(uint32(ch2))
for !nxp.ADC2.HS.HasBits(nxp.ADC_HS_COCO0) {
}
val = nxp.ADC2.R0.Get() & 0xFFFF
}
// should never be zero, but just in case, use UINT16_MAX so that the scalar
// gets factored out of the conversion result, leaving the original reading
// to be returned unaltered/unscaled.
if adcMaximum == 0 {
adcMaximum = 0xFFFF
}
// scale up to a 16-bit value
return uint16((val * 0xFFFF) / adcMaximum)
}
return 0
}
// mode constructs bit masks for mode and average - used in ADC configuration
// registers - from a given ADC bit size (resolution) and sample count.
func (a ADC) mode(resolution, samples uint32) (mode, average uint32) {
// use asynchronous clock (ADACK) (0 = IPG, 1 = IPG/2, or 3 = ADACK)
mode = (nxp.ADC_CFG_ADICLK_ADICLK_3 << nxp.ADC_CFG_ADICLK_Pos) & nxp.ADC_CFG_ADICLK_Msk
// input clock DIV2 (0 = DIV1, 1 = DIV2, 2 = DIV4, or 3 = DIV8)
mode |= (nxp.ADC_CFG_ADIV_ADIV_1 << nxp.ADC_CFG_ADIV_Pos) & nxp.ADC_CFG_ADIV_Msk
switch resolution {
case 8: // 8-bit conversion, sample period (ADC clocks) = 8
mode |= (nxp.ADC_CFG_MODE_MODE_0 << nxp.ADC_CFG_MODE_Pos) & nxp.ADC_CFG_MODE_Msk
mode |= (nxp.ADC_CFG_ADSTS_ADSTS_3 << nxp.ADC_CFG_ADSTS_Pos) & nxp.ADC_CFG_ADSTS_Msk
case 12: // 12-bit conversion, sample period (ADC clocks) = 24
mode |= (nxp.ADC_CFG_MODE_MODE_2 << nxp.ADC_CFG_MODE_Pos) & nxp.ADC_CFG_MODE_Msk
mode |= (nxp.ADC_CFG_ADSTS_ADSTS_3 << nxp.ADC_CFG_ADSTS_Pos) & nxp.ADC_CFG_ADSTS_Msk
mode |= nxp.ADC_CFG_ADLSMP
default: // 10-bit conversion, sample period (ADC clocks) = 20
mode |= (nxp.ADC_CFG_MODE_MODE_1 << nxp.ADC_CFG_MODE_Pos) & nxp.ADC_CFG_MODE_Msk
mode |= (nxp.ADC_CFG_ADSTS_ADSTS_2 << nxp.ADC_CFG_ADSTS_Pos) & nxp.ADC_CFG_ADSTS_Msk
mode |= nxp.ADC_CFG_ADLSMP
}
if samples >= 4 {
if samples >= 32 {
// 32 samples averaged
mode |= (nxp.ADC_CFG_AVGS_AVGS_3 << nxp.ADC_CFG_AVGS_Pos) & nxp.ADC_CFG_AVGS_Msk
} else if samples >= 16 {
// 16 samples averaged
mode |= (nxp.ADC_CFG_AVGS_AVGS_2 << nxp.ADC_CFG_AVGS_Pos) & nxp.ADC_CFG_AVGS_Msk
} else if samples >= 8 {
// 8 samples averaged
mode |= (nxp.ADC_CFG_AVGS_AVGS_1 << nxp.ADC_CFG_AVGS_Pos) & nxp.ADC_CFG_AVGS_Msk
} else {
// 4 samples averaged
mode |= (nxp.ADC_CFG_AVGS_AVGS_0 << nxp.ADC_CFG_AVGS_Pos) & nxp.ADC_CFG_AVGS_Msk
}
average = nxp.ADC_GC_AVGE
}
return mode, average
}
// isCalibrating returns true if and only if either one (or both) of ADC1 and
// ADC2 have their calibrating flags set. ADC reads must wait until these flags
// are clear before attempting a conversion.
func (a ADC) isCalibrating() bool {
return nxp.ADC1.GC.HasBits(nxp.ADC_GC_CAL) || nxp.ADC2.GC.HasBits(nxp.ADC_GC_CAL)
}
const noADCChannel = uint8(0xFF)
// getADCChannel returns the input channel for ADC1/ADC2 of the receiver Pin p.
func (p Pin) getADCChannel() (adc1, adc2 uint8, ok bool) {
switch p {
case PA12: // [AD_B0_12]: ADC1_IN1 ~
return 1, noADCChannel, true
case PA13: // [AD_B0_13]: ADC1_IN2 ~
return 2, noADCChannel, true
case PA14: // [AD_B0_14]: ADC1_IN3 ~
return 3, noADCChannel, true
case PA15: // [AD_B0_15]: ADC1_IN4 ~
return 4, noADCChannel, true
case PA16: // [AD_B1_00]: ADC1_IN5 ADC2_IN5
return 5, 5, true
case PA17: // [AD_B1_01]: ADC1_IN6 ADC2_IN6
return 6, 6, true
case PA18: // [AD_B1_02]: ADC1_IN7 ADC2_IN7
return 7, 7, true
case PA19: // [AD_B1_03]: ADC1_IN8 ADC2_IN8
return 8, 8, true
case PA20: // [AD_B1_04]: ADC1_IN9 ADC2_IN9
return 9, 9, true
case PA21: // [AD_B1_05]: ADC1_IN10 ADC2_IN10
return 10, 10, true
case PA22: // [AD_B1_06]: ADC1_IN11 ADC2_IN11
return 11, 11, true
case PA23: // [AD_B1_07]: ADC1_IN12 ADC2_IN12
return 12, 12, true
case PA24: // [AD_B1_08]: ADC1_IN13 ADC2_IN13
return 13, 13, true
case PA25: // [AD_B1_09]: ADC1_IN14 ADC2_IN14
return 14, 14, true
case PA26: // [AD_B1_10]: ADC1_IN15 ADC2_IN15
return 15, 15, true
case PA27: // [AD_B1_11]: ADC1_IN0 ADC2_IN0
return 16, 16, true
case PA28: // [AD_B1_12]: ~ ADC2_IN1
return noADCChannel, 1, true
case PA29: // [AD_B1_13]: ~ ADC2_IN2
return noADCChannel, 2, true
case PA30: // [AD_B1_14]: ~ ADC2_IN3
return noADCChannel, 3, true
case PA31: // [AD_B1_15]: ~ ADC2_IN4
return noADCChannel, 4, true
default:
return noADCChannel, noADCChannel, false
}
}
+252
View File
@@ -0,0 +1,252 @@
//go:build mimxrt1062
// +build mimxrt1062
package machine
// SPI peripheral abstraction layer for the MIMXRT1062
import (
"device/nxp"
"errors"
"unsafe"
)
// SPIConfig is used to store config info for SPI.
type SPIConfig struct {
Frequency uint32
SDI Pin
SDO Pin
SCK Pin
CS Pin
LSBFirst bool
Mode uint8
}
func (c SPIConfig) getPins() (di, do, ck, cs Pin) {
if 0 == c.SDI && 0 == c.SDO && 0 == c.SCK && 0 == c.CS {
// default pins if none specified
return SPI_SDI_PIN, SPI_SDO_PIN, SPI_SCK_PIN, SPI_CS_PIN
}
return c.SDI, c.SDO, c.SCK, c.CS
}
type SPI struct {
Bus *nxp.LPSPI_Type
// these hold the input selector ("daisy chain") values that select which pins
// are connected to the LPSPI device, and should be defined where the SPI
// instance is declared (e.g., in the board definition). see the godoc
// comments on type muxSelect for more details.
muxSDI, muxSDO, muxSCK, muxCS muxSelect
// these are copied from SPIConfig, during (*SPI).Configure(SPIConfig), and
// should be considered read-only for internal reference (i.e., modifying them
// will have no desirable effect).
sdi, sdo, sck, cs Pin
frequency uint32
// auxiliary state data used internally
configured bool
}
const (
statusTxDataRequest = nxp.LPSPI_SR_TDF // Transmit data flag
statusRxDataReady = nxp.LPSPI_SR_RDF // Receive data flag
statusWordComplete = nxp.LPSPI_SR_WCF // Word Complete flag
statusFrameComplete = nxp.LPSPI_SR_FCF // Frame Complete flag
statusTransferComplete = nxp.LPSPI_SR_TCF // Transfer Complete flag
statusTransmitError = nxp.LPSPI_SR_TEF // Transmit Error flag (FIFO underrun)
statusReceiveError = nxp.LPSPI_SR_REF // Receive Error flag (FIFO overrun)
statusDataMatch = nxp.LPSPI_SR_DMF // Data Match flag
statusModuleBusy = nxp.LPSPI_SR_MBF // Module Busy flag
statusAll = nxp.LPSPI_SR_TDF | nxp.LPSPI_SR_RDF |
nxp.LPSPI_SR_WCF | nxp.LPSPI_SR_FCF | nxp.LPSPI_SR_TCF | nxp.LPSPI_SR_TEF |
nxp.LPSPI_SR_REF | nxp.LPSPI_SR_DMF | nxp.LPSPI_SR_MBF
)
var (
errSPINotConfigured = errors.New("SPI interface is not yet configured")
)
// Configure is intended to setup an SPI interface for transmit/receive.
func (spi *SPI) Configure(config SPIConfig) {
const defaultSpiFreq = 4000000 // 4 MHz
// init pins
spi.sdi, spi.sdo, spi.sck, spi.cs = config.getPins()
// configure the mux and pad control registers
spi.sdi.Configure(PinConfig{Mode: PinModeSPISDI})
spi.sdo.Configure(PinConfig{Mode: PinModeSPISDO})
spi.sck.Configure(PinConfig{Mode: PinModeSPICLK})
spi.cs.Configure(PinConfig{Mode: PinModeSPICS})
// configure the mux input selector
spi.muxSDI.connect()
spi.muxSDO.connect()
spi.muxSCK.connect()
spi.muxCS.connect()
// software reset of LPSPI state registers
spi.Bus.CR.SetBits(nxp.LPSPI_CR_RST)
// also reset FIFOs (not performed by software reset above)
spi.Bus.CR.SetBits(nxp.LPSPI_CR_RRF | nxp.LPSPI_CR_RTF)
spi.Bus.CR.Set(0)
// set controller mode, and input data is sampled on delayed SCK edge
spi.Bus.CFGR1.Set(nxp.LPSPI_CFGR1_MASTER | nxp.LPSPI_CFGR1_SAMPLE)
spi.frequency = config.Frequency
if 0 == spi.frequency {
spi.frequency = defaultSpiFreq
}
// configure LPSPI clock divisor and CS assertion delays
div := spi.getClockDivisor(config.Frequency)
ccr := (div << nxp.LPSPI_CCR_SCKDIV_Pos) & nxp.LPSPI_CCR_SCKDIV_Msk
ccr |= ((div / 2) << nxp.LPSPI_CCR_DBT_Pos) & nxp.LPSPI_CCR_DBT_Msk
ccr |= ((div / 2) << nxp.LPSPI_CCR_PCSSCK_Pos) & nxp.LPSPI_CCR_PCSSCK_Msk
spi.Bus.CCR.Set(ccr)
// 8-bit frame size (words)
tcr := uint32(7)
if config.LSBFirst {
tcr |= nxp.LPSPI_TCR_LSBF
}
// set polarity and phase
switch config.Mode {
case Mode1:
tcr |= nxp.LPSPI_TCR_CPHA
case Mode2:
tcr |= nxp.LPSPI_TCR_CPOL
case Mode3:
tcr |= nxp.LPSPI_TCR_CPOL
tcr |= nxp.LPSPI_TCR_CPHA
}
spi.Bus.TCR.Set(tcr)
// clear FIFO water marks
spi.setWatermark(0, 0)
// enable LPSPI module
spi.Bus.CR.Set(nxp.LPSPI_CR_MEN)
spi.configured = true
}
// Transfer writes/reads a single byte using the SPI interface.
func (spi *SPI) Transfer(w byte) (byte, error) {
if !spi.configured {
return 0, errSPINotConfigured
}
const readTryMax = 10000
for spi.Bus.SR.HasBits(statusModuleBusy) {
} // wait for SPI busy bit to clear
_, txFIFOSize := spi.getFIFOSize()
spi.flushFIFO(true, true)
spi.Bus.SR.Set(statusAll) // clear all status flags (W1C)
// enable LPSPI module
spi.Bus.CR.Set(nxp.LPSPI_CR_MEN)
// TODO: unnecessary since we just flushed the FIFO?
for { // wait for TX FIFO to not be full
if _, txFIFO := spi.getFIFOCount(); txFIFO < txFIFOSize {
break
}
}
// write out byte to TX FIFO
spi.Bus.TDR.Set(uint32(w))
// try to read from RX FIFO if anything exists
didRead := false
data := byte(0)
for i := 0; !didRead && (i < readTryMax); i++ {
rxFIFO, _ := spi.getFIFOCount()
didRead = rxFIFO > 0
if didRead {
data = byte(spi.Bus.RDR.Get())
}
}
// if nothing was read, then wait for transfer complete flag to decide when
// we are finished
if !didRead {
for !spi.Bus.SR.HasBits(nxp.LPSPI_SR_TCF) {
} // wait for all transfers complete flag to set
}
return data, nil
}
func (spi *SPI) isHardwareCSPin(pin Pin) bool {
switch unsafe.Pointer(spi.Bus) {
case unsafe.Pointer(nxp.LPSPI1):
return SPI1_CS_PIN == pin
case unsafe.Pointer(nxp.LPSPI2):
return SPI2_CS_PIN == pin
case unsafe.Pointer(nxp.LPSPI3):
return SPI3_CS_PIN == pin
}
return false
}
func (spi *SPI) hasHardwareCSPin() bool {
return spi.isHardwareCSPin(spi.cs)
}
// getClockDivisor finds the SPI prescalar that minimizes the error between
// requested frequency and possible frequencies available with the LPSPI clock.
// this routine is based on Teensyduino (libraries/SPI/SPI.cpp):
// `void SPIClass::setClockDivider_noInline(uint32_t clk)`
func (spi *SPI) getClockDivisor(freq uint32) uint32 {
const clock = 132000000 // LPSPI root clock frequency (PLL2)
d := uint32(clock)
if freq > 0 {
d /= freq
}
if d > 0 && clock/d > freq {
d++
}
if d > 257 {
return 255
}
if d > 2 {
return d - 2
}
return 0
}
func (spi *SPI) getFIFOSize() (rx, tx uint32) {
param := spi.Bus.PARAM.Get()
return uint32(1) << ((param & nxp.LPSPI_PARAM_RXFIFO_Msk) >> nxp.LPSPI_PARAM_RXFIFO_Pos),
uint32(1) << ((param & nxp.LPSPI_PARAM_TXFIFO_Msk) >> nxp.LPSPI_PARAM_TXFIFO_Pos)
}
func (spi *SPI) getFIFOCount() (rx, tx uint32) {
fsr := spi.Bus.FSR.Get()
return (fsr & nxp.LPSPI_FSR_RXCOUNT_Msk) >> nxp.LPSPI_FSR_RXCOUNT_Pos,
(fsr & nxp.LPSPI_FSR_TXCOUNT_Msk) >> nxp.LPSPI_FSR_TXCOUNT_Pos
}
func (spi *SPI) flushFIFO(rx, tx bool) {
var flush uint32
if rx {
flush |= nxp.LPSPI_CR_RRF
}
if tx {
flush |= nxp.LPSPI_CR_RTF
}
spi.Bus.CR.SetBits(flush)
}
func (spi *SPI) setWatermark(rx, tx uint32) {
spi.Bus.FCR.Set(((rx << nxp.LPSPI_FCR_RXWATER_Pos) & nxp.LPSPI_FCR_RXWATER_Msk) |
((tx << nxp.LPSPI_FCR_TXWATER_Pos) & nxp.LPSPI_FCR_TXWATER_Msk))
}
-52
View File
@@ -7,58 +7,6 @@ import (
"device/nrf"
)
// Hardware pins
const (
P0_00 Pin = 0
P0_01 Pin = 1
P0_02 Pin = 2
P0_03 Pin = 3
P0_04 Pin = 4
P0_05 Pin = 5
P0_06 Pin = 6
P0_07 Pin = 7
P0_08 Pin = 8
P0_09 Pin = 9
P0_10 Pin = 10
P0_11 Pin = 11
P0_12 Pin = 12
P0_13 Pin = 13
P0_14 Pin = 14
P0_15 Pin = 15
P0_16 Pin = 16
P0_17 Pin = 17
P0_18 Pin = 18
P0_19 Pin = 19
P0_20 Pin = 20
P0_21 Pin = 21
P0_22 Pin = 22
P0_23 Pin = 23
P0_24 Pin = 24
P0_25 Pin = 25
P0_26 Pin = 26
P0_27 Pin = 27
P0_28 Pin = 28
P0_29 Pin = 29
P0_30 Pin = 30
P0_31 Pin = 31
P1_00 Pin = 32
P1_01 Pin = 33
P1_02 Pin = 34
P1_03 Pin = 35
P1_04 Pin = 36
P1_05 Pin = 37
P1_06 Pin = 38
P1_07 Pin = 39
P1_08 Pin = 40
P1_09 Pin = 41
P1_10 Pin = 42
P1_11 Pin = 43
P1_12 Pin = 44
P1_13 Pin = 45
P1_14 Pin = 46
P1_15 Pin = 47
)
// Get peripheral and pin number for this GPIO pin.
func (p Pin) getPortPin() (*nrf.GPIO_Type, uint32) {
if p >= 32 {
+109 -25
View File
@@ -5,58 +5,142 @@ package machine
import (
"device/rp"
"errors"
"sync"
)
// ADCChannel is the ADC peripheral mux channel. 0-4.
type ADCChannel uint8
// ADC channels. Only ADC_TEMP_SENSOR is public. The other channels are accessed via Machine.ADC objects
const (
adc0_CH ADCChannel = iota
adc1_CH
adc2_CH
adc3_CH // Note: GPIO29 not broken out on pico board
ADC_TEMP_SENSOR // Internal temperature sensor channel
)
// Used to serialise ADC sampling
var adcLock sync.Mutex
// ADC peripheral reference voltage (mV)
var adcAref uint32
// InitADC resets the ADC peripheral.
func InitADC() {
// reset ADC
rp.RESETS.RESET.SetBits(rp.RESETS_RESET_ADC)
rp.RESETS.RESET.ClearBits(rp.RESETS_RESET_ADC)
for !rp.RESETS.RESET_DONE.HasBits(rp.RESETS_RESET_ADC) {
}
// enable ADC
rp.ADC.CS.Set(rp.ADC_CS_EN)
adcAref = 3300
waitForReady()
}
// Configure configures a ADC pin to be able to be used to read data.
func (a ADC) Configure(config ADCConfig) {
switch a.Pin {
case ADC0, ADC1, ADC2, ADC3:
a.Pin.Configure(PinConfig{Mode: PinAnalog})
default:
// invalid ADC
return
// Configure sets the ADC pin to analog input mode.
func (a ADC) Configure(config ADCConfig) error {
c, err := a.GetADCChannel()
if err != nil {
return err
}
return c.Configure(config)
}
// Get returns a one-shot ADC sample reading.
func (a ADC) Get() uint16 {
rp.ADC.CS.SetBits(uint32(a.getADCChannel()) << rp.ADC_CS_AINSEL_Pos)
if c, err := a.GetADCChannel(); err == nil {
return c.getOnce()
}
// Not an ADC pin!
return 0
}
// GetADCChannel returns the channel associated with the ADC pin.
func (a ADC) GetADCChannel() (c ADCChannel, err error) {
err = nil
switch a.Pin {
case ADC0:
c = adc0_CH
case ADC1:
c = adc1_CH
case ADC2:
c = adc2_CH
case ADC3:
c = adc3_CH
default:
err = errors.New("no ADC channel for pin value")
}
return c, err
}
// 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
}
if p, err := c.Pin(); err == nil {
p.Configure(PinConfig{Mode: PinAnalog})
}
if c == ADC_TEMP_SENSOR {
// Enable temperature sensor bias source
rp.ADC.CS.SetBits(rp.ADC_CS_TS_EN)
}
return nil
}
// getOnce returns a one-shot ADC sample reading from an ADC channel.
func (c ADCChannel) getOnce() uint16 {
// Make it safe to sample multiple ADC channels in separate go routines.
adcLock.Lock()
rp.ADC.CS.ReplaceBits(uint32(c), 0b111, rp.ADC_CS_AINSEL_Pos)
rp.ADC.CS.SetBits(rp.ADC_CS_START_ONCE)
waitForReady()
adcLock.Unlock()
// rp2040 uses 12-bit sampling, so scale to 16-bit
return uint16(rp.ADC.RESULT.Get() << 4)
// rp2040 is a 12-bit ADC, scale raw reading to 16-bits.
return uint16(rp.ADC.RESULT.Get()) << 4
}
// getVoltage does a one-shot sample and returns a millivolts reading.
// Integer portion is stored in the high 16 bits and fractional in the low 16 bits.
func (c ADCChannel) getVoltage() uint32 {
return (adcAref << 16) / (1 << 12) * uint32(c.getOnce()>>4)
}
// ReadTemperature does a one-shot sample of the internal temperature sensor and returns a milli-celsius reading.
// Only works on the ADC_TEMP_SENSOR channel. aka AINSEL=4. Other channels will return 0
func (c ADCChannel) ReadTemperature() (millicelsius uint32) {
if c != ADC_TEMP_SENSOR {
return
}
// T = 27 - (ADC_voltage - 0.706)/0.001721
return (27000<<16 - (c.getVoltage()-706<<16)*581) >> 16
}
// waitForReady spins waiting for the ADC peripheral to become ready.
func waitForReady() {
for !rp.ADC.CS.HasBits(rp.ADC_CS_READY) {
}
}
func (a ADC) getADCChannel() uint8 {
switch a.Pin {
case ADC0:
return 0
case ADC1:
return 1
case ADC2:
return 2
case ADC3:
return 3
// The Pin method returns the GPIO Pin associated with the ADC mux channel, if it has one.
func (c ADCChannel) Pin() (p Pin, err error) {
err = nil
switch c {
case adc0_CH:
p = ADC0
case adc1_CH:
p = ADC1
case adc2_CH:
p = ADC2
case adc3_CH:
p = ADC3
default:
return 0
err = errors.New("no associated pin for channel")
}
return p, err
}
+44 -98
View File
@@ -74,19 +74,7 @@ var (
func (i2c *I2C) Tx(addr uint16, w, r []byte) error {
// timeout in microseconds.
const timeout = 40 * 1000 // 40ms is a reasonable time for a real-time system.
if len(w) > 0 {
if err := i2c.tx(uint8(addr), w, false, timeout); nil != err {
return err
}
}
if len(r) > 0 {
if err := i2c.rx(uint8(addr), r, false, timeout); nil != err {
return err
}
}
return nil
return i2c.tx(uint8(addr), w, r, timeout)
}
// Configure initializes i2c peripheral and configures I2C config's pins passed.
@@ -239,16 +227,16 @@ func (i2c *I2C) deinit() (resetVal uint32) {
return resetVal
}
// tx is a primitive i2c blocking write to bus routine. timeout is time to wait
// in microseconds since calling this function for write to finish.
func (i2c *I2C) tx(addr uint8, tx []byte, nostop bool, timeout uint64) (err error) {
deadline := ticks() + timeout
// tx performs blocking write followed by read to I2C bus.
func (i2c *I2C) tx(addr uint8, tx, rx []byte, timeout_us uint64) (err error) {
deadline := ticks() + timeout_us
if addr >= 0x80 || isReservedI2CAddr(addr) {
return ErrInvalidTgtAddr
}
tlen := len(tx)
txlen := len(tx)
rxlen := len(rx)
// Quick return if possible.
if tlen == 0 {
if txlen == 0 && rxlen == 0 {
return nil
}
@@ -258,17 +246,18 @@ func (i2c *I2C) tx(addr uint8, tx []byte, nostop bool, timeout uint64) (err erro
}
i2c.Bus.IC_TAR.Set(uint32(addr))
i2c.enable()
// If no timeout was passed timeoutCheck is false.
abort := false
var abortReason uint32
byteCtr := 0
for ; byteCtr < tlen; byteCtr++ {
first := byteCtr == 0
last := byteCtr == tlen-1
for txCtr := 0; txCtr < txlen; txCtr++ {
if abort {
break
}
first := txCtr == 0
last := txCtr == txlen-1 && rxlen == 0
i2c.Bus.IC_DATA_CMD.Set(
(boolToBit(first && i2c.restartOnNext) << rp.I2C0_IC_DATA_CMD_RESTART_Pos) |
(boolToBit(last && !nostop) << rp.I2C0_IC_DATA_CMD_STOP_Pos) |
uint32(tx[byteCtr]))
(boolToBit(last) << rp.I2C0_IC_DATA_CMD_STOP_Pos) |
uint32(tx[txCtr]))
// Wait until the transmission of the address/data from the internal
// shift register has completed. For this to function correctly, the
@@ -288,7 +277,6 @@ func (i2c *I2C) tx(addr uint8, tx []byte, nostop bool, timeout uint64) (err erro
// any activity, then with ic_en=0, this bit is set to 0.
for !i2c.interrupted(rp.I2C0_IC_RAW_INTR_STAT_TX_EMPTY) {
if ticks() > deadline {
i2c.restartOnNext = nostop
return errI2CWriteTimeout // If there was a timeout, don't attempt to do anything else.
}
}
@@ -298,7 +286,7 @@ func (i2c *I2C) tx(addr uint8, tx []byte, nostop bool, timeout uint64) (err erro
i2c.clearAbortReason()
abort = true
}
if abort || (last && !nostop) {
if abort || last {
// If the transaction was aborted or if it completed
// successfully wait until the STOP condition has occured.
@@ -307,7 +295,6 @@ func (i2c *I2C) tx(addr uint8, tx []byte, nostop bool, timeout uint64) (err erro
// to take care of the abort.
for !i2c.interrupted(rp.I2C0_IC_RAW_INTR_STAT_STOP_DET) {
if ticks() > deadline {
i2c.restartOnNext = nostop
return errI2CWriteTimeout
}
}
@@ -315,6 +302,33 @@ func (i2c *I2C) tx(addr uint8, tx []byte, nostop bool, timeout uint64) (err erro
}
}
if rxlen > 0 && !abort {
for rxCtr := 0; rxCtr < rxlen; rxCtr++ {
first := rxCtr == 0
last := rxCtr == rxlen-1
for i2c.writeAvailable() == 0 {
}
i2c.Bus.IC_DATA_CMD.Set(
boolToBit(first && i2c.restartOnNext)<<rp.I2C0_IC_DATA_CMD_RESTART_Pos |
boolToBit(last)<<rp.I2C0_IC_DATA_CMD_STOP_Pos |
rp.I2C0_IC_DATA_CMD_CMD) // -> 1 for read
for !abort && i2c.readAvailable() == 0 {
abortReason = i2c.getAbortReason()
i2c.clearAbortReason()
if abortReason != 0 {
abort = true
}
if ticks() > deadline {
return errI2CReadTimeout // If there was a timeout, don't attempt to do anything else.
}
}
if abort {
break
}
rx[rxCtr] = uint8(i2c.Bus.IC_DATA_CMD.Get())
}
}
// From Pico SDK: A lot of things could have just happened due to the ingenious and
// creative design of I2C. Try to figure things out.
if abort {
@@ -327,78 +341,9 @@ func (i2c *I2C) tx(addr uint8, tx []byte, nostop bool, timeout uint64) (err erro
// Address acknowledged, some data not acknowledged
fallthrough
default:
// panic("unknown i2c abortReason:" + strconv.Itoa(abortReason)
err = makeI2CAbortError(abortReason)
}
}
// nostop means we are now at the end of a *message* but not the end of a *transfer*
i2c.restartOnNext = nostop
return err
}
// rx is a primitive i2c blocking read routine. timeout is time to wait
// in microseconds since calling this function for read to finish.
func (i2c *I2C) rx(addr uint8, rx []byte, nostop bool, timeout uint64) (err error) {
deadline := ticks() + timeout
if addr >= 0x80 || isReservedI2CAddr(addr) {
return ErrInvalidTgtAddr
}
rlen := len(rx)
// Quick return if possible.
if rlen == 0 {
return nil
}
err = i2c.disable()
if err != nil {
return err
}
i2c.Bus.IC_TAR.Set(uint32(addr))
i2c.enable()
// If no timeout was passed timeoutCheck is false.
abort := false
var abortReason uint32
byteCtr := 0
for ; byteCtr < rlen; byteCtr++ {
first := byteCtr == 0
last := byteCtr == rlen-1
for i2c.writeAvailable() == 0 {
}
i2c.Bus.IC_DATA_CMD.Set(
boolToBit(first && i2c.restartOnNext)<<rp.I2C0_IC_DATA_CMD_RESTART_Pos |
boolToBit(last && !nostop)<<rp.I2C0_IC_DATA_CMD_STOP_Pos |
rp.I2C0_IC_DATA_CMD_CMD) // -> 1 for read
for !abort && i2c.readAvailable() == 0 {
abortReason = i2c.getAbortReason()
i2c.clearAbortReason()
if abortReason != 0 {
abort = true
}
if ticks() > deadline {
i2c.restartOnNext = nostop
return errI2CReadTimeout // If there was a timeout, don't attempt to do anything else.
}
}
if abort {
break
}
rx[byteCtr] = uint8(i2c.Bus.IC_DATA_CMD.Get())
}
if abort {
switch {
case abortReason == 0 || abortReason&rp.I2C0_IC_TX_ABRT_SOURCE_ABRT_7B_ADDR_NOACK != 0:
// No reported errors - seems to happen if there is nothing connected to the bus.
// Address byte not acknowledged
err = ErrI2CGeneric
default:
// undefined abort sequence
err = makeI2CAbortError(abortReason)
}
}
i2c.restartOnNext = nostop
return err
}
@@ -423,6 +368,7 @@ func (i2c *I2C) clearAbortReason() {
i2c.Bus.IC_CLR_TX_ABRT.Get()
}
// getAbortReason reads IC_TX_ABRT_SOURCE register.
//go:inline
func (i2c *I2C) getAbortReason() uint32 {
return i2c.Bus.IC_TX_ABRT_SOURCE.Get()
+2 -2
View File
@@ -1,5 +1,5 @@
//go:build !baremetal || (stm32 && !stm32f7x2 && !stm32l5x2) || fe310 || k210 || atmega
// +build !baremetal stm32,!stm32f7x2,!stm32l5x2 fe310 k210 atmega
//go:build !baremetal || (stm32 && !stm32f7x2 && !stm32l5x2) || fe310 || k210 || (nxp && !mk66f18) || atmega
// +build !baremetal stm32,!stm32f7x2,!stm32l5x2 fe310 k210 nxp,!mk66f18 atmega
package machine
+18
View File
@@ -18,6 +18,24 @@ var (
ErrExist = errors.New("file exists")
)
// The following code is copied from the official implementation.
// src/internal/poll/fd.go
// ErrDeadlineExceeded is returned for an expired deadline.
// This is exported by the os package as os.ErrDeadlineExceeded.
var ErrDeadlineExceeded error = &DeadlineExceededError{}
// DeadlineExceededError is returned for an expired deadline.
type DeadlineExceededError struct{}
// Implement the net.Error interface.
// The string is "i/o timeout" because that is what was returned
// by earlier Go versions. Changing it may break programs that
// match on error strings.
func (e *DeadlineExceededError) Error() string { return "i/o timeout" }
func (e *DeadlineExceededError) Timeout() bool { return true }
func (e *DeadlineExceededError) Temporary() bool { return true }
// The following code is copied from the official implementation.
// https://github.com/golang/go/blob/4ce6a8e89668b87dce67e2f55802903d6eb9110a/src/os/error.go#L65-L104
+2 -2
View File
@@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package os
//go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris || windows
// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris windows
package os
import (
"syscall"
)
+9 -2
View File
@@ -31,9 +31,14 @@ func TestTempDir(t *testing.T) {
func TestChdir(t *testing.T) {
// create and cd into a new directory
oldDir, err := Getwd()
if err != nil {
t.Errorf("Getwd() returned %v", err)
return
}
dir := "_os_test_TestChDir"
Remove(dir)
err := Mkdir(dir, 0755)
err = Mkdir(dir, 0755)
defer Remove(dir) // even though not quite sure which directory it will execute in
if err != nil {
t.Errorf("Mkdir(%s, 0755) returned %v", dir, err)
@@ -55,7 +60,9 @@ func TestChdir(t *testing.T) {
t.Errorf("Close %s: %s", file, err)
}
// cd back to original directory
err = Chdir("..")
// TODO: emulate "cd .." in wasi-libc better?
//err = Chdir("..")
err = Chdir(oldDir)
if err != nil {
t.Errorf("Chdir ..: %s", err)
}
+56
View File
@@ -0,0 +1,56 @@
//go:build windows || darwin || (linux && !baremetal && !wasi)
// +build windows darwin linux,!baremetal,!wasi
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test pipes on Unix and Windows systems.
package os_test
import (
"bytes"
"os"
"testing"
)
// TestSmokePipe is a simple smoke test for Pipe().
func TestSmokePipe(t *testing.T) {
// Procedure:
// 1. Get the bytes
// 2. Light the bytes on fire
// 3. Smoke the bytes
r, w, err := os.Pipe()
if err != nil {
t.Fatal(err)
return // TODO: remove once Fatal is fatal
}
defer r.Close()
defer w.Close()
msg := []byte("Sed nvlla nisi ardva virtvs")
n, err := w.Write(msg)
if err != nil {
t.Errorf("Writing to fresh pipe failed, error %v", err)
}
want := len(msg)
if n != want {
t.Errorf("Writing to fresh pipe wrote %d bytes, expected %d", n, want)
}
buf := make([]byte, 2*len(msg))
n, err = r.Read(buf)
if err != nil {
t.Errorf("Reading from pipe failed, error %v", err)
}
if n != want {
t.Errorf("Reading from pipe got %d bytes, expected %d", n, want)
}
// Read() does not set len(buf), so do it here.
buf = buf[:n]
if !bytes.Equal(buf, msg) {
t.Errorf("Reading from fresh pipe got wrong bytes")
}
}
+7
View File
@@ -310,6 +310,13 @@ func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer {
index = 0
// Reset numFreeBlocks as allocations cannot wrap.
numFreeBlocks = 0
// In rare cases, the initial heap might be so small that there are
// no blocks at all. In this case, it's better to jump back to the
// start of the loop and try again, until the GC realizes there is
// no memory and grows the heap.
// This can sometimes happen on WebAssembly, where the initial heap
// is created by whatever is left on the last memory page.
continue
}
// Is the block we're looking at free?
+153 -34
View File
@@ -12,14 +12,23 @@ import (
// The underlying hashmap structure for Go.
type hashmap struct {
next *hashmap // hashmap after evacuate (for iterators)
buckets unsafe.Pointer // pointer to array of buckets
count uintptr
keySize uint8 // maybe this can store the key type as well? E.g. keysize == 5 means string?
valueSize uint8
bucketBits uint8
keyEqual func(x, y unsafe.Pointer, n uintptr) bool
keyHash func(key unsafe.Pointer, size uintptr) uint32
}
type hashmapAlgorithm uint8
const (
hashmapAlgorithmBinary hashmapAlgorithm = iota
hashmapAlgorithmString
hashmapAlgorithmInterface
)
// A hashmap bucket. A bucket is a container of 8 key/value pairs: first the
// following two entries, then the 8 keys, then the 8 values. This somewhat odd
// ordering is to make sure the keys and values are well aligned when one of
@@ -32,9 +41,11 @@ type hashmapBucket struct {
}
type hashmapIterator struct {
bucketNumber uintptr
bucket *hashmapBucket
bucketIndex uint8
buckets unsafe.Pointer // pointer to array of hashapBuckets
numBuckets uintptr // length of buckets array
bucketNumber uintptr // current index into buckets array
bucket *hashmapBucket // current bucket in chain
bucketIndex uint8 // current index into bucket
}
// Get the topmost 8 bits of the hash, without using a special value (like 0).
@@ -48,7 +59,7 @@ func hashmapTopHash(hash uint32) uint8 {
}
// Create a new hashmap with the given keySize and valueSize.
func hashmapMake(keySize, valueSize uint8, sizeHint uintptr) *hashmap {
func hashmapMake(keySize, valueSize uint8, sizeHint uintptr, alg uint8) *hashmap {
numBuckets := sizeHint / 8
bucketBits := uint8(0)
for numBuckets != 0 {
@@ -57,14 +68,67 @@ func hashmapMake(keySize, valueSize uint8, sizeHint uintptr) *hashmap {
}
bucketBufSize := unsafe.Sizeof(hashmapBucket{}) + uintptr(keySize)*8 + uintptr(valueSize)*8
buckets := alloc(bucketBufSize*(1<<bucketBits), nil)
keyHash := hashmapKeyHashAlg(hashmapAlgorithm(alg))
keyEqual := hashmapKeyEqualAlg(hashmapAlgorithm(alg))
return &hashmap{
buckets: buckets,
keySize: keySize,
valueSize: valueSize,
bucketBits: bucketBits,
keyEqual: keyEqual,
keyHash: keyHash,
}
}
func hashmapKeyEqualAlg(alg hashmapAlgorithm) func(x, y unsafe.Pointer, n uintptr) bool {
switch alg {
case hashmapAlgorithmBinary:
return memequal
case hashmapAlgorithmString:
return hashmapStringEqual
case hashmapAlgorithmInterface:
return hashmapInterfaceEqual
default:
// compiler bug :(
return nil
}
}
func hashmapKeyHashAlg(alg hashmapAlgorithm) func(key unsafe.Pointer, n uintptr) uint32 {
switch alg {
case hashmapAlgorithmBinary:
return hash32
case hashmapAlgorithmString:
return hashmapStringPtrHash
case hashmapAlgorithmInterface:
return hashmapInterfacePtrHash
default:
// compiler bug :(
return nil
}
}
func hashmapShouldGrow(m *hashmap) bool {
if m.bucketBits > uint8((unsafe.Sizeof(uintptr(0))*8)-3) {
// Over this limit, we're likely to overflow uintptrs during calculations
// or numbers of hash elements. Don't allow any more growth.
// With 29 bits, this is 2^32 elements anyway.
return false
}
// "maximum" number of elements is 0.75 * buckets * elements per bucket
// to avoid overflow, this is calculated as
// max = 3 * (1/4 * buckets * elements per bucket)
// = 3 * (buckets * (elements per bucket)/4)
// = 3 * (buckets * (8/4)
// = 3 * (buckets * 2)
// = 6 * buckets
max := (uintptr(6) << m.bucketBits)
return m.count > max
}
// Return the number of entries in this hashmap, called from the len builtin.
// A nil hashmap is defined as having length 0.
//go:inline
@@ -83,13 +147,11 @@ func hashmapLenUnsafePointer(p unsafe.Pointer) int {
// Set a specified key to a given value. Grow the map if necessary.
//go:nobounds
func hashmapSet(m *hashmap, key unsafe.Pointer, value unsafe.Pointer, hash uint32, keyEqual func(x, y unsafe.Pointer, n uintptr) bool) {
func hashmapSet(m *hashmap, key unsafe.Pointer, value unsafe.Pointer, hash uint32) {
tophash := hashmapTopHash(hash)
if m.buckets == nil {
// No bucket was allocated yet, do so now.
m.buckets = unsafe.Pointer(hashmapInsertIntoNewBucket(m, key, value, tophash))
return
if hashmapShouldGrow(m) {
hashmapGrow(m)
}
numBuckets := uintptr(1) << m.bucketBits
@@ -118,7 +180,7 @@ func hashmapSet(m *hashmap, key unsafe.Pointer, value unsafe.Pointer, hash uint3
}
if bucket.tophash[i] == tophash {
// Could be an existing key that's the same.
if keyEqual(key, slotKey, uintptr(m.keySize)) {
if m.keyEqual(key, slotKey, uintptr(m.keySize)) {
// found same key, replace it
memcpy(slotValue, value, uintptr(m.valueSize))
return
@@ -158,9 +220,35 @@ func hashmapInsertIntoNewBucket(m *hashmap, key, value unsafe.Pointer, tophash u
return bucket
}
func hashmapGrow(m *hashmap) {
// clone map as empty
n := *m
n.count = 0
// allocate our new buckets twice as big
n.bucketBits = m.bucketBits + 1
numBuckets := uintptr(1) << n.bucketBits
bucketBufSize := unsafe.Sizeof(hashmapBucket{}) + uintptr(m.keySize)*8 + uintptr(m.valueSize)*8
n.buckets = alloc(bucketBufSize*numBuckets, nil)
// use a hashmap iterator to go through the old map
var it hashmapIterator
var key = alloc(uintptr(m.keySize), nil)
var value = alloc(uintptr(m.valueSize), nil)
for hashmapNext(m, &it, key, value) {
h := m.keyHash(key, uintptr(m.keySize))
hashmapSet(&n, key, value, h)
}
*m = n
}
// Get the value of a specified key, or zero the value if not found.
//go:nobounds
func hashmapGet(m *hashmap, key, value unsafe.Pointer, valueSize uintptr, hash uint32, keyEqual func(x, y unsafe.Pointer, n uintptr) bool) bool {
func hashmapGet(m *hashmap, key, value unsafe.Pointer, valueSize uintptr, hash uint32) bool {
if m == nil {
// Getting a value out of a nil map is valid. From the spec:
// > if the map is nil or does not contain such an entry, a[x] is the
@@ -189,7 +277,7 @@ func hashmapGet(m *hashmap, key, value unsafe.Pointer, valueSize uintptr, hash u
slotValue := unsafe.Pointer(uintptr(unsafe.Pointer(bucket)) + slotValueOffset)
if bucket.tophash[i] == tophash {
// This could be the key we're looking for.
if keyEqual(key, slotKey, uintptr(m.keySize)) {
if m.keyEqual(key, slotKey, uintptr(m.keySize)) {
// Found the key, copy it.
memcpy(value, slotValue, uintptr(m.valueSize))
return true
@@ -207,7 +295,7 @@ func hashmapGet(m *hashmap, key, value unsafe.Pointer, valueSize uintptr, hash u
// Delete a given key from the map. No-op when the key does not exist in the
// map.
//go:nobounds
func hashmapDelete(m *hashmap, key unsafe.Pointer, hash uint32, keyEqual func(x, y unsafe.Pointer, n uintptr) bool) {
func hashmapDelete(m *hashmap, key unsafe.Pointer, hash uint32) {
if m == nil {
// The delete builtin is defined even when the map is nil. From the spec:
// > If the map m is nil or the element m[k] does not exist, delete is a
@@ -233,7 +321,7 @@ func hashmapDelete(m *hashmap, key unsafe.Pointer, hash uint32, keyEqual func(x,
slotKey := unsafe.Pointer(uintptr(unsafe.Pointer(bucket)) + slotKeyOffset)
if bucket.tophash[i] == tophash {
// This could be the key we're looking for.
if keyEqual(key, slotKey, uintptr(m.keySize)) {
if m.keyEqual(key, slotKey, uintptr(m.keySize)) {
// Found the key, delete it.
bucket.tophash[i] = 0
m.count--
@@ -249,13 +337,16 @@ func hashmapDelete(m *hashmap, key unsafe.Pointer, hash uint32, keyEqual func(x,
//go:nobounds
func hashmapNext(m *hashmap, it *hashmapIterator, key, value unsafe.Pointer) bool {
if m == nil {
// Iterating over a nil slice appears to be allowed by the Go spec:
// https://groups.google.com/g/golang-nuts/c/gVgVLQU1FFE?pli=1
// https://play.golang.org/p/S8jxAMytKDB
// From the spec: If the map is nil, the number of iterations is 0.
return false
}
numBuckets := uintptr(1) << m.bucketBits
if it.buckets == nil {
// initialize iterator
it.buckets = m.buckets
it.numBuckets = uintptr(1) << m.bucketBits
}
for {
if it.bucketIndex >= 8 {
// end of bucket, move to the next in the chain
@@ -263,12 +354,12 @@ func hashmapNext(m *hashmap, it *hashmapIterator, key, value unsafe.Pointer) boo
it.bucket = it.bucket.next
}
if it.bucket == nil {
if it.bucketNumber >= numBuckets {
if it.bucketNumber >= it.numBuckets {
// went through all buckets
return false
}
bucketSize := unsafe.Sizeof(hashmapBucket{}) + uintptr(m.keySize)*8 + uintptr(m.valueSize)*8
bucketAddr := uintptr(m.buckets) + bucketSize*it.bucketNumber
bucketAddr := uintptr(it.buckets) + bucketSize*it.bucketNumber
it.bucket = (*hashmapBucket)(unsafe.Pointer(bucketAddr))
it.bucketNumber++ // next bucket
}
@@ -281,11 +372,29 @@ func hashmapNext(m *hashmap, it *hashmapIterator, key, value unsafe.Pointer) boo
bucketAddr := uintptr(unsafe.Pointer(it.bucket))
slotKeyOffset := unsafe.Sizeof(hashmapBucket{}) + uintptr(m.keySize)*uintptr(it.bucketIndex)
slotKey := unsafe.Pointer(bucketAddr + slotKeyOffset)
slotValueOffset := unsafe.Sizeof(hashmapBucket{}) + uintptr(m.keySize)*8 + uintptr(m.valueSize)*uintptr(it.bucketIndex)
slotValue := unsafe.Pointer(bucketAddr + slotValueOffset)
memcpy(key, slotKey, uintptr(m.keySize))
memcpy(value, slotValue, uintptr(m.valueSize))
it.bucketIndex++
if it.buckets == m.buckets {
// Our view of the buckets is the same as the parent map.
// Just copy the value we have
slotValueOffset := unsafe.Sizeof(hashmapBucket{}) + uintptr(m.keySize)*8 + uintptr(m.valueSize)*uintptr(it.bucketIndex)
slotValue := unsafe.Pointer(bucketAddr + slotValueOffset)
memcpy(value, slotValue, uintptr(m.valueSize))
it.bucketIndex++
} else {
it.bucketIndex++
// Our view of the buckets doesn't match the parent map.
// Look up the key in the new buckets and return that value if it exists
hash := m.keyHash(key, uintptr(m.keySize))
ok := hashmapGet(m, key, value, uintptr(m.valueSize), hash)
if !ok {
// doesn't exist in parent map; try next key
continue
}
// All good.
}
return true
}
@@ -296,7 +405,7 @@ func hashmapNext(m *hashmap, it *hashmapIterator, key, value unsafe.Pointer) boo
func hashmapBinarySet(m *hashmap, key, value unsafe.Pointer) {
// TODO: detect nil map here and throw a better panic message?
hash := hash32(key, uintptr(m.keySize))
hashmapSet(m, key, value, hash, memequal)
hashmapSet(m, key, value, hash)
}
func hashmapBinaryGet(m *hashmap, key, value unsafe.Pointer, valueSize uintptr) bool {
@@ -305,7 +414,7 @@ func hashmapBinaryGet(m *hashmap, key, value unsafe.Pointer, valueSize uintptr)
return false
}
hash := hash32(key, uintptr(m.keySize))
return hashmapGet(m, key, value, valueSize, hash, memequal)
return hashmapGet(m, key, value, valueSize, hash)
}
func hashmapBinaryDelete(m *hashmap, key unsafe.Pointer) {
@@ -313,7 +422,7 @@ func hashmapBinaryDelete(m *hashmap, key unsafe.Pointer) {
return
}
hash := hash32(key, uintptr(m.keySize))
hashmapDelete(m, key, hash, memequal)
hashmapDelete(m, key, hash)
}
// Hashmap with string keys (a common case).
@@ -327,19 +436,24 @@ func hashmapStringHash(s string) uint32 {
return hash32(unsafe.Pointer(_s.ptr), uintptr(_s.length))
}
func hashmapStringPtrHash(sptr unsafe.Pointer, size uintptr) uint32 {
_s := *(*_string)(sptr)
return hash32(unsafe.Pointer(_s.ptr), uintptr(_s.length))
}
func hashmapStringSet(m *hashmap, key string, value unsafe.Pointer) {
hash := hashmapStringHash(key)
hashmapSet(m, unsafe.Pointer(&key), value, hash, hashmapStringEqual)
hashmapSet(m, unsafe.Pointer(&key), value, hash)
}
func hashmapStringGet(m *hashmap, key string, value unsafe.Pointer, valueSize uintptr) bool {
hash := hashmapStringHash(key)
return hashmapGet(m, unsafe.Pointer(&key), value, valueSize, hash, hashmapStringEqual)
return hashmapGet(m, unsafe.Pointer(&key), value, valueSize, hash)
}
func hashmapStringDelete(m *hashmap, key string) {
hash := hashmapStringHash(key)
hashmapDelete(m, unsafe.Pointer(&key), hash, hashmapStringEqual)
hashmapDelete(m, unsafe.Pointer(&key), hash)
}
// Hashmap with interface keys (for everything else).
@@ -427,21 +541,26 @@ func hashmapInterfaceHash(itf interface{}) uint32 {
}
}
func hashmapInterfacePtrHash(iptr unsafe.Pointer, size uintptr) uint32 {
_i := *(*_interface)(iptr)
return hashmapInterfaceHash(_i)
}
func hashmapInterfaceEqual(x, y unsafe.Pointer, n uintptr) bool {
return *(*interface{})(x) == *(*interface{})(y)
}
func hashmapInterfaceSet(m *hashmap, key interface{}, value unsafe.Pointer) {
hash := hashmapInterfaceHash(key)
hashmapSet(m, unsafe.Pointer(&key), value, hash, hashmapInterfaceEqual)
hashmapSet(m, unsafe.Pointer(&key), value, hash)
}
func hashmapInterfaceGet(m *hashmap, key interface{}, value unsafe.Pointer, valueSize uintptr) bool {
hash := hashmapInterfaceHash(key)
return hashmapGet(m, unsafe.Pointer(&key), value, valueSize, hash, hashmapInterfaceEqual)
return hashmapGet(m, unsafe.Pointer(&key), value, valueSize, hash)
}
func hashmapInterfaceDelete(m *hashmap, key interface{}) {
hash := hashmapInterfaceHash(key)
hashmapDelete(m, unsafe.Pointer(&key), hash, hashmapInterfaceEqual)
hashmapDelete(m, unsafe.Pointer(&key), hash)
}
+11
View File
@@ -74,3 +74,14 @@ func nanotime() int64 {
func os_sigpipe() {
runtimePanic("too many writes on closed pipe")
}
// LockOSThread wires the calling goroutine to its current operating system thread.
// Stub for now
// Called by go1.18 standard library on windows, see https://github.com/golang/go/issues/49320
func LockOSThread() {
}
// UnlockOSThread undoes an earlier call to LockOSThread.
// Stub for now
func UnlockOSThread() {
}
+12 -3
View File
@@ -153,9 +153,18 @@ func Kill(pid int, sig Signal) (err error) {
type SysProcAttr struct{}
func Pipe2(p []int, flags int) (err error) {
return ENOSYS // TODO
}
// TODO
type WaitStatus uint32
func (w WaitStatus) Exited() bool { return false }
func (w WaitStatus) ExitStatus() int { return 0 }
func (w WaitStatus) Signaled() bool { return false }
func (w WaitStatus) Signal() Signal { return 0 }
func (w WaitStatus) CoreDump() bool { return false }
func (w WaitStatus) Stopped() bool { return false }
func (w WaitStatus) Continued() bool { return false }
func (w WaitStatus) StopSignal() Signal { return 0 }
func (w WaitStatus) TrapCause() int { return 0 }
func Getenv(key string) (value string, found bool) {
data := cstring(key)
+30 -6
View File
@@ -74,13 +74,20 @@ const (
type Signal int
// Source: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/sys/signal.h
const (
SIGCHLD Signal = 0x14
SIGINT Signal = 0x2
SIGKILL Signal = 0x9
SIGTRAP Signal = 0x5
SIGQUIT Signal = 0x3
SIGTERM Signal = 0xf
SIGINT Signal = 2 /* interrupt */
SIGQUIT Signal = 3 /* quit */
SIGILL Signal = 4 /* illegal instruction (not reset when caught) */
SIGTRAP Signal = 5 /* trace trap (not reset when caught) */
SIGABRT Signal = 6 /* abort() */
SIGFPE Signal = 8 /* floating point exception */
SIGKILL Signal = 9 /* kill (cannot be caught or ignored) */
SIGBUS Signal = 10 /* bus error */
SIGSEGV Signal = 11 /* segmentation violation */
SIGPIPE Signal = 13 /* write on a pipe with no one to read it */
SIGTERM Signal = 15 /* software termination signal from kill */
SIGCHLD Signal = 20 /* to parent on child stop or exit */
)
func (s Signal) Signal() {}
@@ -239,6 +246,19 @@ func Fdopendir(fd int) (dir uintptr, err error) {
return
}
func Pipe2(fds []int, flags int) (err error) {
// Mac only has Pipe, which ignores the flags argument
buf := make([]int32, 2)
fail := int(libc_pipe(&buf[0]))
if fail < 0 {
err = getErrno()
} else {
fds[0] = int(buf[0])
fds[1] = int(buf[1])
}
return
}
func readdir_r(dir uintptr, entry *Dirent, result **Dirent) (err error) {
e1 := libc_readdir_r(unsafe.Pointer(dir), unsafe.Pointer(entry), unsafe.Pointer(result))
if e1 != 0 {
@@ -271,3 +291,7 @@ func libc_fstat(fd int32, ptr unsafe.Pointer) int32
// int lstat(const char *path, struct stat * buf);
//export lstat$INODE64
func libc_lstat(pathname *byte, ptr unsafe.Pointer) int32
// int pipe(int32 *fds);
//export pipe
func libc_pipe(fds *int32) int32
@@ -63,3 +63,7 @@ var libcErrno uintptr
func getErrno() error {
return Errno(libcErrno)
}
func Pipe2(p []int, flags int) (err error) {
return ENOSYS // TODO
}
+15 -3
View File
@@ -9,16 +9,24 @@ import (
)
// https://github.com/WebAssembly/wasi-libc/blob/main/expected/wasm32-wasi/predefined-macros.txt
// disagrees with ../../lib/wasi-libc/libc-top-half/musl/arch/wasm32/bits/signal.h for SIGCHLD?
// https://github.com/WebAssembly/wasi-libc/issues/271
type Signal int
const (
SIGCHLD Signal = 16
SIGINT Signal = 2
SIGKILL Signal = 9
SIGTRAP Signal = 5
SIGQUIT Signal = 3
SIGILL Signal = 4
SIGTRAP Signal = 5
SIGABRT Signal = 6
SIGBUS Signal = 7
SIGFPE Signal = 8
SIGKILL Signal = 9
SIGSEGV Signal = 11
SIGPIPE Signal = 13
SIGTERM Signal = 15
SIGCHLD Signal = 17
)
func (s Signal) Signal() {}
@@ -284,6 +292,10 @@ func Lstat(path string, p *Stat_t) (err error) {
return
}
func Pipe2(p []int, flags int) (err error) {
return ENOSYS // TODO
}
// int stat(const char *path, struct stat * buf);
//export stat
func libc_stat(pathname *byte, ptr unsafe.Pointer) int32
+3
View File
@@ -180,6 +180,9 @@ type SysProcAttr struct {
func Getgroups() ([]int, error) { return []int{1}, nil }
func Gettimeofday(tv *Timeval) error { return ENOSYS }
func Kill(pid int, signum Signal) error { return ENOSYS }
func Pipe2(p []int, flags int) (err error) {
return ENOSYS // TODO
}
func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
return 0, ENOSYS
}
+143
View File
@@ -0,0 +1,143 @@
package testing
import (
"errors"
"fmt"
"reflect"
"time"
)
// InternalFuzzTarget is an internal type but exported because it is
// cross-package; it is part of the implementation of the "go test" command.
type InternalFuzzTarget struct {
Name string
Fn func(f *F)
}
// F is a type passed to fuzz tests.
//
// Fuzz tests run generated inputs against a provided fuzz target, which can
// find and report potential bugs in the code being tested.
//
// A fuzz test runs the seed corpus by default, which includes entries provided
// by (*F).Add and entries in the testdata/fuzz/<FuzzTestName> directory. After
// any necessary setup and calls to (*F).Add, the fuzz test must then call
// (*F).Fuzz to provide the fuzz target. See the testing package documentation
// for an example, and see the F.Fuzz and F.Add method documentation for
// details.
//
// *F methods can only be called before (*F).Fuzz. Once the test is
// executing the fuzz target, only (*T) methods can be used. The only *F methods
// that are allowed in the (*F).Fuzz function are (*F).Failed and (*F).Name.
type F struct {
common
fuzzContext *fuzzContext
testContext *testContext
// inFuzzFn is true when the fuzz function is running. Most F methods cannot
// be called when inFuzzFn is true.
inFuzzFn bool
// corpus is a set of seed corpus entries, added with F.Add and loaded
// from testdata.
corpus []corpusEntry
result fuzzResult
fuzzCalled bool
}
// corpusEntry is an alias to the same type as internal/fuzz.CorpusEntry.
// We use a type alias because we don't want to export this type, and we can't
// import internal/fuzz from testing.
type corpusEntry = struct {
Parent string
Path string
Data []byte
Values []interface{}
Generation int
IsSeed bool
}
// Add will add the arguments to the seed corpus for the fuzz test. This will be
// a no-op if called after or within the fuzz target, and args must match the
// arguments for the fuzz target.
func (f *F) Add(args ...interface{}) {
var values []interface{}
for i := range args {
if t := reflect.TypeOf(args[i]); !supportedTypes[t] {
panic(fmt.Sprintf("testing: unsupported type to Add %v", t))
}
values = append(values, args[i])
}
f.corpus = append(f.corpus, corpusEntry{Values: values, IsSeed: true, Path: fmt.Sprintf("seed#%d", len(f.corpus))})
}
// supportedTypes represents all of the supported types which can be fuzzed.
var supportedTypes = map[reflect.Type]bool{
reflect.TypeOf(([]byte)("")): true,
reflect.TypeOf((string)("")): true,
reflect.TypeOf((bool)(false)): true,
reflect.TypeOf((byte)(0)): true,
reflect.TypeOf((rune)(0)): true,
reflect.TypeOf((float32)(0)): true,
reflect.TypeOf((float64)(0)): true,
reflect.TypeOf((int)(0)): true,
reflect.TypeOf((int8)(0)): true,
reflect.TypeOf((int16)(0)): true,
reflect.TypeOf((int32)(0)): true,
reflect.TypeOf((int64)(0)): true,
reflect.TypeOf((uint)(0)): true,
reflect.TypeOf((uint8)(0)): true,
reflect.TypeOf((uint16)(0)): true,
reflect.TypeOf((uint32)(0)): true,
reflect.TypeOf((uint64)(0)): true,
}
// Fuzz runs the fuzz function, ff, for fuzz testing. If ff fails for a set of
// arguments, those arguments will be added to the seed corpus.
//
// ff must be a function with no return value whose first argument is *T and
// whose remaining arguments are the types to be fuzzed.
// For example:
//
// f.Fuzz(func(t *testing.T, b []byte, i int) { ... })
//
// The following types are allowed: []byte, string, bool, byte, rune, float32,
// float64, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64.
// More types may be supported in the future.
//
// ff must not call any *F methods, e.g. (*F).Log, (*F).Error, (*F).Skip. Use
// the corresponding *T method instead. The only *F methods that are allowed in
// the (*F).Fuzz function are (*F).Failed and (*F).Name.
//
// This function should be fast and deterministic, and its behavior should not
// depend on shared state. No mutatable input arguments, or pointers to them,
// should be retained between executions of the fuzz function, as the memory
// backing them may be mutated during a subsequent invocation. ff must not
// modify the underlying data of the arguments provided by the fuzzing engine.
//
// When fuzzing, F.Fuzz does not return until a problem is found, time runs out
// (set with -fuzztime), or the test process is interrupted by a signal. F.Fuzz
// should be called exactly once, unless F.Skip or F.Fail is called beforehand.
func (f *F) Fuzz(ff interface{}) {
f.failed = true
f.result.N = 0
f.result.T = 0
f.result.Error = errors.New("operation not implemented")
return
}
// fuzzContext holds fields common to all fuzz tests.
type fuzzContext struct {
deps testDeps
mode fuzzMode
}
type fuzzMode uint8
// fuzzResult contains the results of a fuzz run.
type fuzzResult struct {
N int // The number of iterations.
T time.Duration // The total time taken.
Error error // Error is the error from the failing input
}
-9
View File
@@ -430,15 +430,6 @@ type testDeps interface {
MatchString(pat, str string) (bool, error)
}
func MainStart(deps interface{}, tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample) *M {
Init()
return &M{
Tests: tests,
Benchmarks: benchmarks,
deps: deps.(testDeps),
}
}
// Run runs the tests. It returns an exit code to pass to os.Exit.
func (m *M) Run() (code int) {
defer func() {
+16
View File
@@ -0,0 +1,16 @@
//go:build go1.18
// +build go1.18
package testing
// MainStart is meant for use by tests generated by 'go test'.
// It is not meant to be called directly and is not subject to the Go 1 compatibility document.
// It may change signature from release to release.
func MainStart(deps interface{}, tests []InternalTest, benchmarks []InternalBenchmark, fuzzTargets []InternalFuzzTarget, examples []InternalExample) *M {
Init()
return &M{
Tests: tests,
Benchmarks: benchmarks,
deps: deps.(testDeps),
}
}
+16
View File
@@ -0,0 +1,16 @@
//go:build !go1.18
// +build !go1.18
package testing
// MainStart is meant for use by tests generated by 'go test'.
// It is not meant to be called directly and is not subject to the Go 1 compatibility document.
// It may change signature from release to release.
func MainStart(deps interface{}, tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample) *M {
Init()
return &M{
Tests: tests,
Benchmarks: benchmarks,
deps: deps.(testDeps),
}
}
+1 -1
View File
@@ -6,5 +6,5 @@
"-Wl,--defsym=_stack_size=512"
],
"flash-command": "avrdude -c arduino -p atmega328p -b 57600 -P {port} -U flash:w:{hex}:i",
"emulator": ["simavr", "-m", "atmega328p", "-f", "16000000"]
"emulator": "simavr -m atmega328p -f 16000000 {}"
}
+1 -1
View File
@@ -7,5 +7,5 @@
],
"flash-command": "avrdude -c arduino -p atmega328p -P {port} -U flash:w:{hex}:i",
"serial-port": ["acm:2341:0043", "acm:2341:0001", "acm:2a03:0043", "acm:2341:0243"],
"emulator": ["simavr", "-m", "atmega328p", "-f", "16000000"]
"emulator": "simavr -m atmega328p -f 16000000 {}"
}
+1 -1
View File
@@ -13,5 +13,5 @@
"targets/avr.S",
"src/device/avr/atmega1284p.s"
],
"emulator": ["simavr", "-m", "atmega1284p", "-f", "20000000"]
"emulator": "simavr -m atmega1284p -f 20000000 {}"
}
+1 -1
View File
@@ -5,5 +5,5 @@
"extra-files": [
"targets/cortex-m-qemu.s"
],
"emulator": ["qemu-system-arm", "-machine", "lm3s6965evb", "-semihosting", "-nographic", "-kernel"]
"emulator": "qemu-system-arm -machine lm3s6965evb -semihosting -nographic -kernel {}"
}
+1 -1
View File
@@ -14,7 +14,7 @@
"-fshort-enums",
"-fomit-frame-pointer",
"-mfloat-abi=soft",
"-fno-exceptions", "-fno-unwind-tables",
"-fno-exceptions", "-fno-unwind-tables", "-fno-asynchronous-unwind-tables",
"-ffunction-sections", "-fdata-sections"
],
"ldflags": [
+1 -1
View File
@@ -2,5 +2,5 @@
"inherits": ["cortex-m"],
"llvm-target": "thumbv6m-unknown-unknown-eabi",
"cpu": "cortex-m0",
"features": "+armv6-m,+soft-float,+strict-align,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp"
"features": "+armv6-m,+soft-float,+strict-align,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp"
}
+1 -1
View File
@@ -2,5 +2,5 @@
"inherits": ["cortex-m"],
"llvm-target": "thumbv6m-unknown-unknown-eabi",
"cpu": "cortex-m0plus",
"features": "+armv6-m,+soft-float,+strict-align,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp"
"features": "+armv6-m,+soft-float,+strict-align,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp"
}
+1 -1
View File
@@ -2,5 +2,5 @@
"inherits": ["cortex-m"],
"llvm-target": "thumbv7m-unknown-unknown-eabi",
"cpu": "cortex-m3",
"features": "+armv7-m,+hwdiv,+soft-float,+strict-align,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp"
"features": "+armv7-m,+hwdiv,+soft-float,+strict-align,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp"
}
+1 -1
View File
@@ -2,5 +2,5 @@
"inherits": ["cortex-m"],
"llvm-target": "thumbv7em-unknown-unknown-eabi",
"cpu": "cortex-m4",
"features": "+armv7e-m,+dsp,+hwdiv,+soft-float,+strict-align,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp"
"features": "+armv7e-m,+dsp,+hwdiv,+soft-float,+strict-align,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp"
}
+1 -1
View File
@@ -2,5 +2,5 @@
"inherits": ["cortex-m"],
"llvm-target": "thumbv7em-unknown-unknown-eabi",
"cpu": "cortex-m7",
"features": "+armv7e-m,+dsp,+hwdiv,+soft-float,+strict-align,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp"
"features": "+armv7e-m,+dsp,+hwdiv,+soft-float,+strict-align,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp"
}
+1 -1
View File
@@ -6,5 +6,5 @@
"-Wl,--defsym=_stack_size=128"
],
"flash-command": "micronucleus --run {hex}",
"emulator": ["simavr", "-m", "attiny85", "-f", "16000000"]
"emulator": "simavr -m attiny85 -f 16000000 {}"
}
+4 -1
View File
@@ -1,6 +1,7 @@
{
"inherits": ["xtensa"],
"cpu": "esp32",
"features": "+atomctl,+bool,+coprocessor,+debug,+density,+dfpaccel,+div32,+exception,+fp,+highpriinterrupts,+interrupt,+loop,+mac16,+memctl,+miscsr,+mul32,+mul32high,+nsa,+prid,+regprotect,+rvector,+s32c1i,+sext,+threadptr,+timerint,+windowed",
"build-tags": ["esp32", "esp"],
"scheduler": "tasks",
"serial": "uart",
@@ -14,5 +15,7 @@
"src/internal/task/task_stack_esp32.S"
],
"binary-format": "esp32",
"flash-command": "esptool.py --chip=esp32 --port {port} write_flash 0x1000 {bin} -ff 80m -fm dout"
"flash-command": "esptool.py --chip=esp32 --port {port} write_flash 0x1000 {bin} -ff 80m -fm dout",
"emulator": "qemu-system-xtensa -machine esp32 -nographic -drive file={img},if=mtd,format=raw",
"gdb": ["xtensa-esp32-elf-gdb"]
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"inherits": ["riscv32"],
"features": "+c,+m,-relax,-save-restore",
"features": "+c,+m",
"build-tags": ["esp32c3", "esp"],
"serial": "uart",
"rtlib": "compiler-rt",
+1
View File
@@ -1,6 +1,7 @@
{
"inherits": ["xtensa"],
"cpu": "esp8266",
"features": "+debug,+density,+exception,+extendedl32r,+highpriinterrupts,+interrupt,+mul32,+nsa,+prid,+regprotect,+rvector,+timerint",
"build-tags": ["esp8266", "esp"],
"scheduler": "tasks",
"linker": "xtensa-esp32-elf-ld",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"inherits": ["riscv32"],
"cpu": "sifive-e31",
"features": "+a,+c,+m,-64bit,-relax,-save-restore",
"features": "+a,+c,+m",
"build-tags": ["fe310", "sifive"]
}

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