mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-07-30 00:28:41 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 22b5b69cf0 |
+60
-41
@@ -163,17 +163,20 @@ commands:
|
||||
command: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install --no-install-recommends \
|
||||
libgnutls30 libssl1.0.2 \
|
||||
qemu-system-arm \
|
||||
qemu-system-riscv32 \
|
||||
qemu-user \
|
||||
gcc-avr \
|
||||
avr-libc \
|
||||
ninja-build \
|
||||
python3
|
||||
- install-node
|
||||
- install-chrome
|
||||
- install-wasmtime
|
||||
- install-cmake
|
||||
- hack-ninja-jobs
|
||||
- install-xtensa-toolchain:
|
||||
variant: "linux-amd64"
|
||||
- restore_cache:
|
||||
keys:
|
||||
- go-cache-v2-{{ checksum "go.mod" }}-{{ .Environment.CIRCLE_PREVIOUS_BUILD_NUM }}
|
||||
@@ -198,7 +201,12 @@ commands:
|
||||
key: llvm-build-11-linux-v4-assert
|
||||
paths:
|
||||
llvm-build
|
||||
- build-binaryen-linux
|
||||
- build-binaryen-linux-stretch
|
||||
- run:
|
||||
name: "Build TinyGo"
|
||||
command: |
|
||||
make ASSERT=1
|
||||
echo 'export PATH=$(pwd)/build:$PATH' >> $BASH_ENV
|
||||
- build-wasi-libc
|
||||
- run:
|
||||
name: "Test TinyGo"
|
||||
@@ -209,63 +217,73 @@ commands:
|
||||
# necessary to keep memory consumption down and avoid OOM (for a
|
||||
# 2CPU/4GB executor).
|
||||
GOFLAGS: -p=2
|
||||
- run:
|
||||
name: "Build TinyGo"
|
||||
command: |
|
||||
make ASSERT=1
|
||||
echo 'export PATH=$(pwd)/build:$PATH' >> $BASH_ENV
|
||||
- run: make tinygo-test
|
||||
- save_cache:
|
||||
key: go-cache-v2-{{ checksum "go.mod" }}-{{ .Environment.CIRCLE_BUILD_NUM }}
|
||||
paths:
|
||||
- ~/.cache/go-build
|
||||
- /go/pkg/mod
|
||||
- install-xtensa-toolchain:
|
||||
variant: "linux-amd64"
|
||||
- run: make gen-device -j4
|
||||
- run: make smoketest
|
||||
- install-chrome
|
||||
- run: make tinygo-test
|
||||
- run: make wasmtest
|
||||
build-linux:
|
||||
steps:
|
||||
- checkout
|
||||
- submodules
|
||||
- run:
|
||||
name: "Install apt dependencies"
|
||||
name: "Install apk dependencies"
|
||||
command: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install --no-install-recommends \
|
||||
libgnutls30 libssl1.0.2 \
|
||||
ninja-build \
|
||||
python3
|
||||
- install-cmake
|
||||
- hack-ninja-jobs
|
||||
apk add git openssh make g++ gcompat
|
||||
- checkout
|
||||
- run:
|
||||
name: "Install Go"
|
||||
command: |
|
||||
wget https://dl.google.com/go/go1.17.3.linux-amd64.tar.gz
|
||||
tar -C /usr/local -xzf go1.17.3.linux-amd64.tar.gz
|
||||
ln -s /usr/local/go/bin/go /usr/local/bin/go
|
||||
#- submodules
|
||||
- restore_cache:
|
||||
name: "Restore Go cache"
|
||||
keys:
|
||||
- go-cache-v2-{{ checksum "go.mod" }}-{{ .Environment.CIRCLE_PREVIOUS_BUILD_NUM }}
|
||||
- go-cache-v2-{{ checksum "go.mod" }}
|
||||
- llvm-source-linux
|
||||
- go-cache-alpine-v2-{{ checksum "go.mod" }}-{{ .Environment.CIRCLE_PREVIOUS_BUILD_NUM }}
|
||||
- go-cache-alpine-v2-{{ checksum "go.mod" }}
|
||||
- restore_cache:
|
||||
name: "Restore llvm-source cache"
|
||||
keys:
|
||||
- llvm-build-11-linux-v4-noassert
|
||||
- llvm-source-11-alpine-v2-x0
|
||||
- run:
|
||||
name: "Fetch LLVM source"
|
||||
command: make llvm-source
|
||||
- save_cache:
|
||||
name: "Save llvm-source cache"
|
||||
key: llvm-source-11-alpine-v2-x0
|
||||
paths:
|
||||
- llvm-project
|
||||
#- llvm-project/clang/lib/Headers
|
||||
#- llvm-project/clang/include
|
||||
#- llvm-project/lld/include
|
||||
#- llvm-project/llvm/include
|
||||
- restore_cache:
|
||||
name: "Restore llvm-build cache"
|
||||
keys:
|
||||
- llvm-build-11-alpine-v1-noassert-x0
|
||||
- run:
|
||||
name: "Build LLVM"
|
||||
command: |
|
||||
if [ ! -f llvm-build/lib/liblldELF.a ]
|
||||
then
|
||||
# fetch LLVM source (may only have headers right now)
|
||||
rm -rf llvm-project
|
||||
make llvm-source
|
||||
#rm -rf llvm-project
|
||||
#make llvm-source
|
||||
# install dependencies
|
||||
apk add cmake samurai python3
|
||||
# build!
|
||||
make llvm-build
|
||||
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
|
||||
SAMUFLAGS=-j3 make llvm-build
|
||||
#find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
|
||||
fi
|
||||
- save_cache:
|
||||
key: llvm-build-11-linux-v4-noassert
|
||||
name: "Save llvm-build cache"
|
||||
key: llvm-build-11-alpine-v1-noassert-x0
|
||||
paths:
|
||||
llvm-build
|
||||
- build-binaryen-linux-stretch
|
||||
- build-wasi-libc
|
||||
- run:
|
||||
name: "Install fpm"
|
||||
command: |
|
||||
@@ -286,7 +304,8 @@ commands:
|
||||
- store_artifacts:
|
||||
path: /tmp/tinygo_amd64.deb
|
||||
- save_cache:
|
||||
key: go-cache-v2-{{ checksum "go.mod" }}-{{ .Environment.CIRCLE_BUILD_NUM }}
|
||||
name: "Save Go cache"
|
||||
key: go-cache-alpine-v2-{{ checksum "go.mod" }}-{{ .Environment.CIRCLE_BUILD_NUM }}
|
||||
paths:
|
||||
- ~/.cache/go-build
|
||||
- /go/pkg/mod
|
||||
@@ -323,7 +342,7 @@ commands:
|
||||
curl https://dl.google.com/go/go1.17.darwin-amd64.tar.gz -o go1.17.darwin-amd64.tar.gz
|
||||
sudo tar -C /usr/local -xzf go1.17.darwin-amd64.tar.gz
|
||||
ln -s /usr/local/go/bin/go /usr/local/bin/go
|
||||
HOMEBREW_NO_AUTO_UPDATE=1 brew install cmake ninja
|
||||
HOMEBREW_NO_AUTO_UPDATE=1 brew install qemu cmake ninja
|
||||
- install-xtensa-toolchain:
|
||||
variant: "macos"
|
||||
- restore_cache:
|
||||
@@ -388,7 +407,7 @@ commands:
|
||||
- lib/wasi-libc/sysroot
|
||||
- run:
|
||||
name: "Test TinyGo"
|
||||
command: make test GOTESTFLAGS="-v -short"
|
||||
command: make test
|
||||
no_output_timeout: 20m
|
||||
- run:
|
||||
name: "Build TinyGo release"
|
||||
@@ -426,12 +445,12 @@ jobs:
|
||||
llvm: "11"
|
||||
assert-test-linux:
|
||||
docker:
|
||||
- image: circleci/golang:1.17-buster
|
||||
- image: circleci/golang:1.17-stretch
|
||||
steps:
|
||||
- assert-test-linux
|
||||
build-linux:
|
||||
docker:
|
||||
- image: circleci/golang:1.17-stretch
|
||||
- image: alpine:3.14
|
||||
steps:
|
||||
- build-linux
|
||||
test-linux-build:
|
||||
@@ -450,11 +469,11 @@ jobs:
|
||||
workflows:
|
||||
test-all:
|
||||
jobs:
|
||||
- test-llvm11-go115
|
||||
- test-llvm11-go116
|
||||
#- test-llvm11-go115
|
||||
#- test-llvm11-go116
|
||||
- build-linux
|
||||
- test-linux-build:
|
||||
requires:
|
||||
- build-linux
|
||||
- build-macos
|
||||
- assert-test-linux
|
||||
#- build-macos
|
||||
#- assert-test-linux
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
name: Windows
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
#pull_request:
|
||||
push:
|
||||
branches:
|
||||
- dev
|
||||
@@ -15,6 +15,11 @@ jobs:
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: '1.17'
|
||||
- name: Install QEMU
|
||||
shell: bash
|
||||
run: |
|
||||
choco install qemu --version=2020.06.12
|
||||
echo "C:\Program Files\QEMU" >> $GITHUB_PATH
|
||||
- name: Install Ninja
|
||||
shell: bash
|
||||
run: |
|
||||
@@ -73,7 +78,7 @@ jobs:
|
||||
run: make binaryen
|
||||
- name: Test TinyGo
|
||||
shell: bash
|
||||
run: make test GOTESTFLAGS="-v -short"
|
||||
run: make test
|
||||
- name: Build TinyGo release tarball
|
||||
run: make build/release -j4
|
||||
- name: Make release artifact
|
||||
|
||||
@@ -1,97 +1,3 @@
|
||||
0.21.0
|
||||
---
|
||||
|
||||
* **command line**
|
||||
- drop support for LLVM 10
|
||||
- `build`: drop support for LLVM targets in the -target flag
|
||||
- `build`: fix paths in error messages on Windows
|
||||
- `build`: add -p flag to set parallelism
|
||||
- `lldb`: implement `tinygo lldb` subcommand
|
||||
- `test`: use emulator exit code instead of parsing test output
|
||||
- `test`: pass testing arguments to wasmtime
|
||||
* **compiler**
|
||||
- use -opt flag for optimization level in CFlags (-Os, etc)
|
||||
- `builder`: improve accuracy of the -size=full flag
|
||||
- `builder`: hardcode some more frame sizes for __aeabi_* functions
|
||||
- `builder`: add support for -size= flag for WebAssembly
|
||||
- `cgo`: fix line/column reporting in syntax error messages
|
||||
- `cgo`: support function definitions in CGo headers
|
||||
- `cgo`: implement rudimentary C array decaying
|
||||
- `cgo`: add support for stdio in picolibc and wasi-libc
|
||||
- `cgo`: run CGo parser per file, not per CGo fragment
|
||||
- `compiler`: fix unintentionally exported math functions
|
||||
- `compiler`: properly implement div and rem operations
|
||||
- `compiler`: add support for recursive function types
|
||||
- `compiler`: add support for the `go` keyword on interface methods
|
||||
- `compiler`: add minsize attribute for -Oz
|
||||
- `compiler`: add "target-cpu" and "target-features" attributes
|
||||
- `compiler`: fix indices into strings and arrays
|
||||
- `compiler`: fix string compare functions
|
||||
- `interp`: simplify some code to avoid some errors
|
||||
- `interp`: support recursive globals (like linked lists) in globals
|
||||
- `interp`: support constant globals
|
||||
- `interp`: fix reverting of extractvalue/insertvalue with multiple indices
|
||||
- `transform`: work around renamed return type after merging LLVM modules
|
||||
* **standard library**
|
||||
- `internal/bytealg`: fix indexing error in Compare()
|
||||
- `machine`: support Pin.Get() function when the pin is configured as output
|
||||
- `net`, `syscall`: Reduce code duplication by switching to internal/itoa.
|
||||
- `os`: don't try to read executable path on baremetal
|
||||
- `os`: implement Getwd
|
||||
- `os`: add File.WriteString and File.WriteAt
|
||||
- `reflect`: fix type.Size() to account for struct padding
|
||||
- `reflect`: don't construct an interface-in-interface value
|
||||
- `reflect`: implement Value.Elem() for interface values
|
||||
- `reflect`: fix Value.Index() in a specific case
|
||||
- `reflect`: add support for DeepEqual
|
||||
- `runtime`: add another set of invalid unicode runes to encodeUTF8()
|
||||
- `runtime`: only initialize os.runtime_args when needed
|
||||
- `runtime`: only use CRLF on baremetal systems for println
|
||||
- `runtime/debug`: stub `debug.SetMaxStack`
|
||||
- `runtime/debug`: stub `debug.Stack`
|
||||
- `testing`: add a stub for t.Parallel()
|
||||
- `testing`: add support for -test.short flag
|
||||
- `testing`: stub B.ReportAllocs()
|
||||
- `testing`: add `testing.Verbose`
|
||||
- `testing`: stub `testing.AllocsPerRun`
|
||||
* **targets**
|
||||
- fix gen-device-svd to handle 64-bit values
|
||||
- add CPU and Features property to all targets
|
||||
- match LLVM triple to the one Clang uses
|
||||
- `atsam`: simplify definition of SERCOM UART, I2C and SPI peripherals
|
||||
- `atsam`: move I2S0 to machine file
|
||||
- `esp32`: fix SPI configuration
|
||||
- `esp32c3`: add support for GDB debugging
|
||||
- `esp32c3`: add support for CPU interrupts
|
||||
- `esp32c3`: use tasks scheduler by default
|
||||
- `fe310`: increase CPU frequency from 16MHz to 320MHz
|
||||
- `fe310`: add support for bit banging drivers
|
||||
- `linux`: build static binaries using musl
|
||||
- `linux`: reduce binary size by calling `write` instead of `putchar`
|
||||
- `linux`: add support for GOARM
|
||||
- `riscv`: implement 32-bit atomic operations
|
||||
- `riscv`: align the heap to 16 bytes
|
||||
- `riscv`: switch to tasks-based scheduler
|
||||
- `rp2040`: add CPUFrequency()
|
||||
- `rp2040`: improve I2C baud rate configuration
|
||||
- `rp2040`: add pin interrupt API
|
||||
- `rp2040`: refactor PWM code and fix Period calculation
|
||||
- `stm32f103`: fix SPI
|
||||
- `stm32f103`: make SPI frequency selection more flexible
|
||||
- `qemu`: signal correct exit code to QEMU
|
||||
- `wasi`: run C/C++ constructors at startup
|
||||
- `wasm`: ensure heapptr is aligned
|
||||
- `wasm`: update wasi-libc dependency
|
||||
- `wasm`: wasi: use asyncify
|
||||
- `wasm`: support `-scheduler=none`
|
||||
- `windows`: add support for Windows (amd64 only for now)
|
||||
* **boards**
|
||||
- `feather-stm32f405`, `feather-rp2040`: add I2C pin names
|
||||
- `m5stack-core2`: add M5Stack Core2
|
||||
- `nano-33-ble`: SoftDevice s140v7 support
|
||||
- `nano-33-ble`: add constants for more on-board pins
|
||||
|
||||
|
||||
0.20.0
|
||||
---
|
||||
|
||||
|
||||
@@ -18,9 +18,6 @@ LLVM_NM ?= $(word 1,$(abspath $(call detect,llvm-build/bin/llvm-nm))$(call detec
|
||||
GO ?= go
|
||||
export GOROOT = $(shell $(GO) env GOROOT)
|
||||
|
||||
# Flags to pass to go test.
|
||||
GOTESTFLAGS ?= -v
|
||||
|
||||
# md5sum binary
|
||||
MD5SUM = md5sum
|
||||
|
||||
@@ -171,8 +168,8 @@ $(LLVM_BUILDDIR)/build.ninja: llvm-source
|
||||
mkdir -p $(LLVM_BUILDDIR) && cd $(LLVM_BUILDDIR) && cmake -G Ninja $(TINYGO_SOURCE_DIR)/$(LLVM_PROJECTDIR)/llvm "-DLLVM_TARGETS_TO_BUILD=X86;ARM;AArch64;RISCV;WebAssembly" "-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=AVR;Xtensa" -DCMAKE_BUILD_TYPE=Release -DLIBCLANG_BUILD_STATIC=ON -DLLVM_ENABLE_TERMINFO=OFF -DLLVM_ENABLE_ZLIB=OFF -DLLVM_ENABLE_LIBEDIT=OFF -DLLVM_ENABLE_Z3_SOLVER=OFF -DLLVM_ENABLE_OCAMLDOC=OFF -DLLVM_ENABLE_LIBXML2=OFF -DLLVM_ENABLE_PROJECTS="clang;lld" -DLLVM_TOOL_CLANG_TOOLS_EXTRA_BUILD=OFF -DCLANG_ENABLE_STATIC_ANALYZER=OFF -DCLANG_ENABLE_ARCMT=OFF $(LLVM_OPTION)
|
||||
|
||||
# Build LLVM.
|
||||
$(LLVM_BUILDDIR): $(LLVM_BUILDDIR)/build.ninja
|
||||
cd $(LLVM_BUILDDIR) && ninja $(NINJA_BUILD_TARGETS)
|
||||
$(LLVM_BUILDDIR): #$(LLVM_BUILDDIR)/build.ninja
|
||||
cd $(LLVM_BUILDDIR) && ninja llvm-nm #$(NINJA_BUILD_TARGETS)
|
||||
|
||||
# Build Binaryen
|
||||
.PHONY: binaryen
|
||||
@@ -195,7 +192,7 @@ tinygo:
|
||||
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) build -buildmode exe -o build/tinygo$(EXE) -tags byollvm -ldflags="-X main.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 .
|
||||
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test -v -timeout=20m -buildmode exe -tags byollvm ./builder ./cgo ./compileopts ./compiler ./interp ./transform .
|
||||
|
||||
TEST_PACKAGES = \
|
||||
compress/bzip2 \
|
||||
|
||||
@@ -2276,16 +2276,16 @@ func (b *builder) createBinOp(op token.Token, typ, ytyp types.Type, x, y llvm.Va
|
||||
case token.NEQ: // !=
|
||||
result := b.createRuntimeCall("stringEqual", []llvm.Value{x, y}, "")
|
||||
return b.CreateNot(result, ""), nil
|
||||
case token.LSS: // x < y
|
||||
case token.LSS: // <
|
||||
return b.createRuntimeCall("stringLess", []llvm.Value{x, y}, ""), nil
|
||||
case token.LEQ: // x <= y becomes NOT (y < x)
|
||||
case token.LEQ: // <=
|
||||
result := b.createRuntimeCall("stringLess", []llvm.Value{y, x}, "")
|
||||
return b.CreateNot(result, ""), nil
|
||||
case token.GTR: // x > y becomes y < x
|
||||
return b.createRuntimeCall("stringLess", []llvm.Value{y, x}, ""), nil
|
||||
case token.GEQ: // x >= y becomes NOT (x < y)
|
||||
case token.GTR: // >
|
||||
result := b.createRuntimeCall("stringLess", []llvm.Value{x, y}, "")
|
||||
return b.CreateNot(result, ""), nil
|
||||
case token.GEQ: // >=
|
||||
return b.createRuntimeCall("stringLess", []llvm.Value{y, x}, ""), nil
|
||||
default:
|
||||
panic("binop on string: " + op.String())
|
||||
}
|
||||
|
||||
Vendored
+3
-2
@@ -71,8 +71,9 @@ entry:
|
||||
; Function Attrs: nounwind
|
||||
define hidden i1 @main.stringCompareLarger(i8* %s1.data, i32 %s1.len, i8* %s2.data, i32 %s2.len, i8* %context, i8* %parentHandle) unnamed_addr #0 {
|
||||
entry:
|
||||
%0 = call i1 @runtime.stringLess(i8* %s2.data, i32 %s2.len, i8* %s1.data, i32 %s1.len, i8* undef, i8* null) #0
|
||||
ret i1 %0
|
||||
%0 = call i1 @runtime.stringLess(i8* %s1.data, i32 %s1.len, i8* %s2.data, i32 %s2.len, i8* undef, i8* null) #0
|
||||
%1 = xor i1 %0, true
|
||||
ret i1 %1
|
||||
}
|
||||
|
||||
declare i1 @runtime.stringLess(i8*, i32, i8*, i32, i8*, i8*)
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ import (
|
||||
|
||||
// Version of TinyGo.
|
||||
// Update this value before release of new version of software.
|
||||
const Version = "0.21.0"
|
||||
const Version = "0.21.0-dev"
|
||||
|
||||
// GetGorootVersion returns the major and minor version for a given GOROOT path.
|
||||
// If the goroot cannot be determined, (0, 0) is returned.
|
||||
|
||||
+35
-33
@@ -75,6 +75,40 @@ func TestCompiler(t *testing.T) {
|
||||
runPlatTests(optionsFromTarget(""), tests, t)
|
||||
})
|
||||
|
||||
if testing.Short() {
|
||||
return
|
||||
}
|
||||
|
||||
t.Run("EmulatedCortexM3", func(t *testing.T) {
|
||||
runPlatTests(optionsFromTarget("cortex-m-qemu"), tests, t)
|
||||
})
|
||||
|
||||
if runtime.GOOS == "windows" || runtime.GOOS == "darwin" {
|
||||
// Note: running only on Windows and macOS because Linux (as of 2020)
|
||||
// usually has an outdated QEMU version that doesn't support RISC-V yet.
|
||||
t.Run("EmulatedRISCV", func(t *testing.T) {
|
||||
runPlatTests(optionsFromTarget("riscv-qemu"), tests, t)
|
||||
})
|
||||
}
|
||||
|
||||
if runtime.GOOS == "linux" {
|
||||
t.Run("X86Linux", func(t *testing.T) {
|
||||
runPlatTests(optionsFromOSARCH("linux/386"), tests, t)
|
||||
})
|
||||
t.Run("ARMLinux", func(t *testing.T) {
|
||||
runPlatTests(optionsFromOSARCH("linux/arm/6"), tests, t)
|
||||
})
|
||||
t.Run("ARM64Linux", func(t *testing.T) {
|
||||
runPlatTests(optionsFromOSARCH("linux/arm64"), tests, t)
|
||||
})
|
||||
t.Run("WebAssembly", func(t *testing.T) {
|
||||
runPlatTests(optionsFromTarget("wasm"), tests, t)
|
||||
})
|
||||
t.Run("WASI", func(t *testing.T) {
|
||||
runPlatTests(optionsFromTarget("wasi"), tests, t)
|
||||
})
|
||||
}
|
||||
|
||||
// Test a few build options.
|
||||
t.Run("build-options", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
@@ -116,38 +150,6 @@ func TestCompiler(t *testing.T) {
|
||||
}, nil, nil)
|
||||
})
|
||||
})
|
||||
|
||||
if testing.Short() {
|
||||
// Don't test other targets when the -short flag is used. Only test the
|
||||
// host system.
|
||||
return
|
||||
}
|
||||
|
||||
t.Run("EmulatedCortexM3", func(t *testing.T) {
|
||||
runPlatTests(optionsFromTarget("cortex-m-qemu"), tests, t)
|
||||
})
|
||||
|
||||
t.Run("EmulatedRISCV", func(t *testing.T) {
|
||||
runPlatTests(optionsFromTarget("riscv-qemu"), tests, t)
|
||||
})
|
||||
|
||||
if runtime.GOOS == "linux" {
|
||||
t.Run("X86Linux", func(t *testing.T) {
|
||||
runPlatTests(optionsFromOSARCH("linux/386"), tests, t)
|
||||
})
|
||||
t.Run("ARMLinux", func(t *testing.T) {
|
||||
runPlatTests(optionsFromOSARCH("linux/arm/6"), tests, t)
|
||||
})
|
||||
t.Run("ARM64Linux", func(t *testing.T) {
|
||||
runPlatTests(optionsFromOSARCH("linux/arm64"), tests, t)
|
||||
})
|
||||
t.Run("WebAssembly", func(t *testing.T) {
|
||||
runPlatTests(optionsFromTarget("wasm"), tests, t)
|
||||
})
|
||||
t.Run("WASI", func(t *testing.T) {
|
||||
runPlatTests(optionsFromTarget("wasi"), tests, t)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func runPlatTests(options compileopts.Options, tests []string, t *testing.T) {
|
||||
@@ -164,7 +166,7 @@ func runPlatTests(options compileopts.Options, tests []string, t *testing.T) {
|
||||
t.Parallel()
|
||||
runTest("env.go", options, t, []string{"first", "second"}, []string{"ENV1=VALUE1", "ENV2=VALUE2"})
|
||||
})
|
||||
if options.Target == "wasi" || options.Target == "wasm" {
|
||||
if options.Target == "wasi" {
|
||||
t.Run("alias.go-scheduler-none", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
options := compileopts.Options(options)
|
||||
|
||||
@@ -18,12 +18,6 @@ func CPUFrequency() uint32 {
|
||||
return 125 * MHz
|
||||
}
|
||||
|
||||
// Returns the period of a clock cycle for the raspberry pi pico in nanoseconds.
|
||||
// Used in PWM API.
|
||||
func cpuPeriod() uint32 {
|
||||
return 1e9 / CPUFrequency()
|
||||
}
|
||||
|
||||
// clockIndex identifies a hardware clock
|
||||
type clockIndex uint8
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
//go:build rp2040
|
||||
// +build rp2040
|
||||
|
||||
package machine
|
||||
@@ -6,13 +5,12 @@ package machine
|
||||
import (
|
||||
"device/rp"
|
||||
"errors"
|
||||
"math"
|
||||
"runtime/volatile"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrBadPeriod = errors.New("period outside valid range 8ns..268ms")
|
||||
ErrPeriodTooBig = errors.New("period outside valid range 1..4e9ns")
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -52,21 +50,8 @@ func getPWMGroup(index uintptr) *pwmGroup {
|
||||
return (*pwmGroup)(unsafe.Pointer(uintptr(unsafe.Pointer(rp.PWM)) + 0x14*index))
|
||||
}
|
||||
|
||||
// Hardware Pulse Width Modulation (PWM) API
|
||||
// PWM peripherals available on RP2040. Each peripheral has 2 pins available for
|
||||
// a total of 16 available PWM outputs. Some pins may not be available on some boards.
|
||||
//
|
||||
// The RP2040 PWM block has 8 identical slices. Each slice can drive two PWM output signals, or
|
||||
// measure the frequency or duty cycle of an input signal. This gives a total of up to 16 controllable
|
||||
// PWM outputs. All 30 GPIOs can be driven by the PWM block
|
||||
//
|
||||
// The PWM hardware functions by continuously comparing the input value to a free-running counter. This produces a
|
||||
// toggling output where the amount of time spent at the high output level is proportional to the input value. The fraction of
|
||||
// time spent at the high signal level is known as the duty cycle of the signal.
|
||||
//
|
||||
// The default behaviour of a PWM slice is to count upward until the wrap value (\ref pwm_config_set_wrap) is reached, and then
|
||||
// immediately wrap to 0. PWM slices also offer a phase-correct mode, where the counter starts to count downward after
|
||||
// reaching TOP, until it reaches 0 again.
|
||||
var (
|
||||
PWM0 = getPWMGroup(0)
|
||||
PWM1 = getPWMGroup(1)
|
||||
@@ -109,23 +94,30 @@ func (pwm *pwmGroup) peripheral() uint8 {
|
||||
return uint8((uintptr(unsafe.Pointer(pwm)) - uintptr(unsafe.Pointer(rp.PWM))) / 0x14)
|
||||
}
|
||||
|
||||
// SetPeriod updates the period of this PWM peripheral in nanoseconds.
|
||||
// SetPeriod updates the period of this PWM peripheral.
|
||||
// To set a particular frequency, use the following formula:
|
||||
//
|
||||
// period = 1e9 / frequency
|
||||
//
|
||||
// Where frequency is in hertz. If you use a period of 0, a period
|
||||
// that works well for LEDs will be picked.
|
||||
// If you use a period of 0, a period that works well for LEDs will be picked.
|
||||
//
|
||||
// SetPeriod will try not to modify TOP if possible to reach the target period.
|
||||
// If the period is unattainable with current TOP SetPeriod will modify TOP
|
||||
// by the bare minimum to reach the target period. It will also enable phase
|
||||
// correct to reach periods above 130ms.
|
||||
// SetPeriod will not change the prescaler, but also won't change the current
|
||||
// value in any of the channels. This means that you may need to update the
|
||||
// value for the particular channel.
|
||||
//
|
||||
// Note that you cannot pick any arbitrary period after the PWM peripheral has
|
||||
// been configured. If you want to switch between frequencies, pick the lowest
|
||||
// frequency (longest period) once when calling Configure and adjust the
|
||||
// frequency here as needed.
|
||||
func (p *pwmGroup) SetPeriod(period uint64) error {
|
||||
if period > 0xffff_ffff {
|
||||
return ErrPeriodTooBig
|
||||
}
|
||||
if period == 0 {
|
||||
period = 1e5
|
||||
}
|
||||
return p.setPeriod(period)
|
||||
p.setPeriod(period)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Top returns the current counter top, for use in duty cycle calculation.
|
||||
@@ -143,14 +135,14 @@ func (p *pwmGroup) Counter() uint32 {
|
||||
return (p.CTR.Get() & rp.PWM_CH0_CTR_CH0_CTR_Msk) >> rp.PWM_CH0_CTR_CH0_CTR_Pos
|
||||
}
|
||||
|
||||
// Period returns the used PWM period in nanoseconds.
|
||||
// Period returns the used PWM period in nanoseconds. It might deviate slightly
|
||||
// from the configured period due to rounding.
|
||||
func (p *pwmGroup) Period() uint64 {
|
||||
periodPerCycle := cpuPeriod()
|
||||
periodPerCycle := getPeriod()
|
||||
top := p.getWrap()
|
||||
phc := p.getPhaseCorrect()
|
||||
Int, frac := p.getClockDiv()
|
||||
// Line below can overflow if operations done without care.
|
||||
return (16*uint64(Int) + uint64(frac)) * uint64((top+1)*(phc+1)*periodPerCycle) / 16 // cycles = (TOP+1) * (CSRPHCorrect + 1) * (DIV_INT + DIV_FRAC/16)
|
||||
return uint64((Int + frac/16) * (top + 1) * (phc + 1) * periodPerCycle) // cycles = (TOP+1) * (CSRPHCorrect + 1) * (DIV_INT + DIV_FRAC/16)
|
||||
}
|
||||
|
||||
// SetInverting sets whether to invert the output of this channel.
|
||||
@@ -188,12 +180,6 @@ func (p *pwmGroup) SetTop(top uint32) {
|
||||
p.setWrap(uint16(top))
|
||||
}
|
||||
|
||||
// SetCounter sets counter control register. Max value is 16bit (0xffff).
|
||||
// Useful for synchronising two different PWM peripherals.
|
||||
func (p *pwmGroup) SetCounter(ctr uint32) {
|
||||
p.CTR.Set(ctr)
|
||||
}
|
||||
|
||||
// Enable enables or disables PWM peripheral channels.
|
||||
func (p *pwmGroup) Enable(enable bool) {
|
||||
p.enable(enable)
|
||||
@@ -204,6 +190,29 @@ func (p *pwmGroup) IsEnabled() (enabled bool) {
|
||||
return (p.CSR.Get()&rp.PWM_CH0_CSR_EN_Msk)>>rp.PWM_CH0_CSR_EN_Pos != 0
|
||||
}
|
||||
|
||||
// Hardware Pulse Width Modulation (PWM) API
|
||||
//
|
||||
// The RP2040 PWM block has 8 identical slices. Each slice can drive two PWM output signals, or
|
||||
// measure the frequency or duty cycle of an input signal. This gives a total of up to 16 controllable
|
||||
// PWM outputs. All 30 GPIOs can be driven by the PWM block
|
||||
//
|
||||
// The PWM hardware functions by continuously comparing the input value to a free-running counter. This produces a
|
||||
// toggling output where the amount of time spent at the high output level is proportional to the input value. The fraction of
|
||||
// time spent at the high signal level is known as the duty cycle of the signal.
|
||||
//
|
||||
// The default behaviour of a PWM slice is to count upward until the wrap value (\ref pwm_config_set_wrap) is reached, and then
|
||||
// immediately wrap to 0. PWM slices also offer a phase-correct mode, where the counter starts to count downward after
|
||||
// reaching TOP, until it reaches 0 again.
|
||||
type pwms struct {
|
||||
slice pwmGroup
|
||||
hw *rp.PWM_Type
|
||||
}
|
||||
|
||||
// Handle to all pwm peripheral registers.
|
||||
var _PWM = pwms{
|
||||
hw: rp.PWM,
|
||||
}
|
||||
|
||||
// Initialise a PWM with settings from a configuration object.
|
||||
// If start is true then PWM starts on initialization.
|
||||
func (pwm *pwmGroup) init(config PWMConfig, start bool) error {
|
||||
@@ -244,53 +253,24 @@ func (pwm *pwmGroup) setDivMode(mode uint32) {
|
||||
pwm.CSR.ReplaceBits(mode<<rp.PWM_CH0_CSR_DIVMODE_Pos, rp.PWM_CH0_CSR_DIVMODE_Msk, 0)
|
||||
}
|
||||
|
||||
// setPeriod sets the pwm peripheral period (frequency). Calculates DIV_INT,DIV_FRAC and sets it from following equation:
|
||||
// setPeriod sets the pwm peripheral period (frequency). Calculates DIV_INT and sets it from following equation:
|
||||
// cycles = (TOP+1) * (CSRPHCorrect + 1) * (DIV_INT + DIV_FRAC/16)
|
||||
// where cycles is amount of clock cycles per PWM period.
|
||||
func (pwm *pwmGroup) setPeriod(period uint64) error {
|
||||
// This period calculation algorithm consists of
|
||||
// 1. Calculating best-fit prescale at a slightly lower-than-max TOP value
|
||||
// 2. Calculate TOP value to reach target period given the calculated prescale
|
||||
// 3. Apply calculated Prescale from step 1 and calculated Top from step 2
|
||||
const (
|
||||
maxTop = math.MaxUint16
|
||||
// start algorithm at 95% Top. This allows us to undershoot period with prescale.
|
||||
topStart = 95 * maxTop / 100
|
||||
milliseconds = 1_000_000_000
|
||||
// Maximum Period is 268369920ns on rp2040, given by (16*255+15)*8*(1+0xffff)*(1+1)/16
|
||||
// With no phase shift max period is half of this value.
|
||||
maxPeriod = 268 * milliseconds
|
||||
)
|
||||
|
||||
if period > maxPeriod || period < 8 {
|
||||
return ErrBadPeriod
|
||||
}
|
||||
if period > maxPeriod/2 {
|
||||
pwm.setPhaseCorrect(true) // Must enable Phase correct to reach large periods.
|
||||
}
|
||||
|
||||
func (pwm *pwmGroup) setPeriod(period uint64) {
|
||||
targetPeriod := uint32(period)
|
||||
periodPerCycle := getPeriod()
|
||||
top := pwm.getWrap()
|
||||
phc := pwm.getPhaseCorrect()
|
||||
_, frac := pwm.getClockDiv()
|
||||
// clearing above expression:
|
||||
// DIV_INT + DIV_FRAC/16 = cycles / ( (TOP+1) * (CSRPHCorrect+1) ) // DIV_FRAC/16 is always 0 in this equation
|
||||
// DIV_INT = cycles / ( (TOP+1) * (CSRPHCorrect+1) ) - DIV_FRAC/16
|
||||
// where cycles must be converted to time:
|
||||
// target_period = cycles * period_per_cycle ==> cycles = target_period/period_per_cycle
|
||||
periodPerCycle := uint64(cpuPeriod())
|
||||
phc := uint64(pwm.getPhaseCorrect())
|
||||
rhs := 16 * period / ((1 + phc) * periodPerCycle * (1 + topStart)) // right-hand-side of equation, scaled so frac is not divided
|
||||
whole := rhs / 16
|
||||
frac := rhs % 16
|
||||
if whole > 0xff {
|
||||
whole = 0xff
|
||||
Int := targetPeriod/((1+phc)*periodPerCycle*(1+top)) - frac/16
|
||||
if Int > 0xff {
|
||||
Int = 0xff
|
||||
}
|
||||
|
||||
// Step 2 is acquiring a better top value. Clearing the equation:
|
||||
// TOP = cycles / ( (DIVINT+DIVFRAC/16) * (CSRPHCorrect+1) ) - 1
|
||||
top := 16*period/((16*whole+frac)*periodPerCycle*(1+phc)) - 1
|
||||
if top > maxTop {
|
||||
top = maxTop
|
||||
}
|
||||
pwm.SetTop(uint32(top))
|
||||
pwm.setClockDiv(uint8(whole), uint8(frac))
|
||||
return nil
|
||||
pwm.setClockDiv(uint8(Int), 0)
|
||||
}
|
||||
|
||||
// Int is integer value to reduce counting rate by. Must be greater than or equal to 1. DIV_INT is bits 4:11 (8 bits).
|
||||
@@ -380,9 +360,9 @@ func (pwm *pwmGroup) getPhaseCorrect() (phCorrect uint32) {
|
||||
return (pwm.CSR.Get() & rp.PWM_CH0_CSR_PH_CORRECT_Msk) >> rp.PWM_CH0_CSR_PH_CORRECT_Pos
|
||||
}
|
||||
|
||||
func (pwm *pwmGroup) getClockDiv() (Int, frac uint8) {
|
||||
func (pwm *pwmGroup) getClockDiv() (Int, frac uint32) {
|
||||
div := pwm.DIV.Get()
|
||||
return uint8((div & rp.PWM_CH0_DIV_INT_Msk) >> rp.PWM_CH0_DIV_INT_Pos), uint8((div & rp.PWM_CH0_DIV_FRAC_Msk) >> rp.PWM_CH0_DIV_FRAC_Pos)
|
||||
return (div & rp.PWM_CH0_DIV_INT_Msk) >> rp.PWM_CH0_DIV_INT_Pos, (div & rp.PWM_CH0_DIV_FRAC_Msk) >> rp.PWM_CH0_DIV_FRAC_Pos
|
||||
}
|
||||
|
||||
// pwmGPIOToSlice Determine the PWM channel that is attached to the specified GPIO.
|
||||
@@ -396,3 +376,9 @@ func pwmGPIOToSlice(gpio Pin) (slicenum uint8) {
|
||||
func pwmGPIOToChannel(gpio Pin) (channel uint8) {
|
||||
return uint8(gpio) & 1
|
||||
}
|
||||
|
||||
// Returns the period of a clock cycle for the raspberry pi pico in nanoseconds.
|
||||
func getPeriod() uint32 {
|
||||
const periodIn uint32 = 1e9 / (125 * MHz)
|
||||
return periodIn
|
||||
}
|
||||
|
||||
@@ -1,17 +1,2 @@
|
||||
// Package debug is a dummy package that is not yet implemented.
|
||||
package debug
|
||||
|
||||
// SetMaxStack sets the maximum amount of memory that can be used by a single
|
||||
// goroutine stack.
|
||||
//
|
||||
// Not implemented.
|
||||
func SetMaxStack(n int) int {
|
||||
return n
|
||||
}
|
||||
|
||||
// Stack returns a formatted stack trace of the goroutine that calls it.
|
||||
//
|
||||
// Not implemented.
|
||||
func Stack() []byte {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -29,6 +29,34 @@ func setEventHandler(fn func()) {
|
||||
handleEvent = fn
|
||||
}
|
||||
|
||||
//export resume
|
||||
func resume() {
|
||||
go func() {
|
||||
handleEvent()
|
||||
}()
|
||||
|
||||
if wasmNested {
|
||||
minSched()
|
||||
return
|
||||
}
|
||||
|
||||
wasmNested = true
|
||||
scheduler()
|
||||
wasmNested = false
|
||||
}
|
||||
|
||||
//export go_scheduler
|
||||
func go_scheduler() {
|
||||
if wasmNested {
|
||||
minSched()
|
||||
return
|
||||
}
|
||||
|
||||
wasmNested = true
|
||||
scheduler()
|
||||
wasmNested = false
|
||||
}
|
||||
|
||||
func ticksToNanoseconds(ticks timeUnit) int64 {
|
||||
// The JavaScript API works in float64 milliseconds, so convert to
|
||||
// nanoseconds first before converting to a timeUnit (which is a float64),
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
//go:build wasm && !wasi && !scheduler.none
|
||||
// +build wasm,!wasi,!scheduler.none
|
||||
|
||||
package runtime
|
||||
|
||||
//export resume
|
||||
func resume() {
|
||||
go func() {
|
||||
handleEvent()
|
||||
}()
|
||||
|
||||
if wasmNested {
|
||||
minSched()
|
||||
return
|
||||
}
|
||||
|
||||
wasmNested = true
|
||||
scheduler()
|
||||
wasmNested = false
|
||||
}
|
||||
|
||||
//export go_scheduler
|
||||
func go_scheduler() {
|
||||
if wasmNested {
|
||||
minSched()
|
||||
return
|
||||
}
|
||||
|
||||
wasmNested = true
|
||||
scheduler()
|
||||
wasmNested = false
|
||||
}
|
||||
@@ -297,24 +297,6 @@ func Short() bool {
|
||||
return flagShort
|
||||
}
|
||||
|
||||
// Verbose reports whether the -test.v flag is set.
|
||||
func Verbose() bool {
|
||||
return flagVerbose
|
||||
}
|
||||
|
||||
// AllocsPerRun returns the average number of allocations during calls to f.
|
||||
// Although the return value has type float64, it will always be an integral
|
||||
// value.
|
||||
//
|
||||
// Not implemented.
|
||||
func AllocsPerRun(runs int, f func()) (avg float64) {
|
||||
f()
|
||||
for i := 0; i < runs; i++ {
|
||||
f()
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func TestMain(m *M) {
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
Vendored
-7
@@ -24,13 +24,6 @@ func main() {
|
||||
println("ab" < "aa")
|
||||
println("aa" < "ab")
|
||||
|
||||
h := "hello"
|
||||
println("h < h", h < h)
|
||||
println("h <= h", h <= h)
|
||||
println("h == h", h == h)
|
||||
println("h >= h", h >= h)
|
||||
println("h > h", h > h)
|
||||
|
||||
println("array equality")
|
||||
println(a1 == [2]int{1, 2})
|
||||
println(a1 != [2]int{1, 2})
|
||||
|
||||
Vendored
-5
@@ -20,11 +20,6 @@ true
|
||||
false
|
||||
false
|
||||
true
|
||||
h < h false
|
||||
h <= h true
|
||||
h == h true
|
||||
h >= h true
|
||||
h > h false
|
||||
array equality
|
||||
true
|
||||
false
|
||||
|
||||
Reference in New Issue
Block a user