Compare commits

...

57 Commits

Author SHA1 Message Date
deadprogram b9ce6c3374 build: allow building llvm image via workflow dispatch
Signed-off-by: deadprogram <ron@hybridgroup.com>
2025-03-11 13:08:20 +01:00
Ayke van Laethem cab3834bc9 riscv-qemu: add VirtIO RNG device
This implements machine.GetRNG() using VirtIO. This gets the tests to
pass for crypto/md5 and crypto/sha1 that use crypto/rand in their tests.
2025-03-11 04:22:16 -07:00
Elias Naur 7f970a45c2 machine: don't block the rp2xxx UART interrupt handler
Don't block forever if there's nothing to receive. On the other hand,
process the entire FIFO, not just a single byte.

This fixes an issue where the rp2350 would hang after programming through
openocd, where the UART0 interrupt would be spuriously pending.
2025-03-11 02:01:18 -07:00
Ayke van Laethem ebf70ab18e ci: add more tests for wasm and baremetal
Run a range of tests in CI, to make sure browser wasm and baremetal
don't regress too badly.

I have intentionally filtered out tests, so that newly added tests to
TEST_PACKAGES_FAST will be added here as well (and can be excluded if
needed).
2025-03-10 03:26:30 -07:00
Elias Naur 226744a538 machine: correct register address for Pin.SetInterrupt for rp2350 (#4782)
Fixes #4689
2025-03-09 10:26:38 -03:00
Ayke van Laethem dc876c6ed4 ci: add single test for wasm
It looks like we didn't have any tests for wasm. Having one tests is not
much, but it proves that the infrastructure works and it actually
verifies a fix to https://github.com/tinygo-org/tinygo/issues/4777.

We should add more packages to this list in the future.
2025-03-07 09:09:13 -08:00
Ayke van Laethem 5a09084c73 os: add stub Symlink for wasm
This doesn't do anything, but it makes tests work.
2025-03-07 09:09:13 -08:00
Ayke van Laethem 6c9074772c compiler: crypto/internal/sysrand is allowed to use unsafe signatures
Apparently this package imports `runtime.getRandomData` from the gojs
module. This is not yet implemented, but simply allowing this package to
do such imports gets crypto/sha256 to compile.
2025-03-07 09:09:13 -08:00
Ayke van Laethem e49663809b machine: fix RP2040 Pico board on the playground
Right now it doesn't compile, with errors like the following:

    # machine
    /app/tinygo/src/machine/board_pico.go:7:13: undefined: GPIO0
    /app/tinygo/src/machine/board_pico.go:8:13: undefined: GPIO1
    /app/tinygo/src/machine/board_pico.go:9:13: undefined: GPIO2
    /app/tinygo/src/machine/board_pico.go:10:13: undefined: GPIO3
    [...etc...]

This patch should fix that.
2025-03-07 07:20:40 -08:00
Elias Naur 7d6d93f7aa machine: bump rp2040 to 200MHz (#4768)
* machine: add support for core voltage adjustments to rp2040

In preparation for bumping the core frequency of the rp2040, this
change implements the required core voltage adjustment logic.

* machine: bump rp2040 to 200MHz
2025-03-04 08:57:59 -03:00
deadprogram 8c54e3dd88 release: update version to 0.36.0
Signed-off-by: deadprogram <ron@hybridgroup.com>
2025-03-03 13:02:59 -08:00
deadprogram 47c0debe4b docs: update CHANGELOG for 0.36.0 release
Signed-off-by: deadprogram <ron@hybridgroup.com>
2025-03-03 13:02:59 -08:00
Randy Reddig 9a1cde40a8 src/reflect: implement Value.Equal
Implementation copied from Go.
2025-03-03 12:14:30 -08:00
Elias Naur 20fc814635 machine: replace hard-coded cpu frequencies on rp2xxx (#4767)
Missed from the earlier change that bumped the rp2350 frequency.
2025-03-02 08:38:29 -03:00
Egawa Takashi 64d8a04308 convert offset as signed int into unsigned int in syscall/js.stringVal in wasm_exec.js 2025-03-01 09:14:57 -08:00
Elias Naur b95effbdd7 machine: bump rp2350 CPUFrequency to 150 MHz (#4766)
Leave rp2040 speed bump to 200 MHz for a future change, because it
requires bumping the core voltage as well[0].

[0] https://github.com/raspberrypi/pico-sdk/releases/tag/2.1.1
2025-03-01 10:09:53 -03:00
Elias Naur 92c130c7be machine: compute rp2 clock dividers from crystal and target frequency (#4747)
Follow-up to #4728 which implemented the algorithm for finding the
dividers.

The calculation is computed at compile time by interp, as verified by
building example/blinky1 for -target pico.
2025-02-28 19:05:27 -03:00
deadprogram 31c4bc1151 license: update for 2025
Signed-off-by: deadprogram <ron@hybridgroup.com>
2025-02-28 20:56:22 +01:00
deadprogram 42f5e55ed5 docs: small corrections for README regarding wasm
Signed-off-by: deadprogram <ron@hybridgroup.com>
2025-02-28 20:56:22 +01:00
deadprogram 81da7bb4c1 targets: add target for pico2-w board
Signed-off-by: deadprogram <ron@hybridgroup.com>
2025-02-28 20:02:35 +01:00
deadprogram 209754493b make: use GOOS and GOARCH for building wasm simulated boards
Signed-off-by: deadprogram <ron@hybridgroup.com>
2025-02-28 18:02:21 +01:00
deadprogram b0aef96340 fix: only infer target for wasm when GOOS and GOARCH are set correctly, not just based on file extension
Signed-off-by: deadprogram <ron@hybridgroup.com>
2025-02-28 18:02:21 +01:00
Ayke van Laethem 056394e24b make: add test-corpus-wasip2
I wanted to run the test corpus with WASIp2 so I added these lines.
2025-02-28 16:16:12 +01:00
Ayke van Laethem 1545659817 internal/syscall/unix: use our own version of this package
The upstream one assumes it's running on a Unix system (which makes
sense), but this package is also used on baremetal. So replace it on
systems that need a replaced syscall package.
2025-02-27 15:45:23 +01:00
Ayke van Laethem 38e3d55e64 all: add Go 1.24 support 2025-02-25 14:41:42 +01:00
Ayke van Laethem 66da29e89f wasip2: add stubs to get internal/syscall/unix to work
This fixes lots of broken tests in stdlib packages in Go 1.24.
2025-02-25 14:41:42 +01:00
Ayke van Laethem c180d6fe2f testing: add Chdir
This method was added in Go 1.24.
2025-02-25 14:41:42 +01:00
Ayke van Laethem cdea833b5c os: add File.Chdir support
We should really be using syscall.Fchdir here, but this is a fix to get
Go 1.24 working.
2025-02-25 14:41:42 +01:00
Ayke van Laethem c2eaa495df os: implement stub Chdir for non-OS systems 2025-02-25 14:41:42 +01:00
Ayke van Laethem 3476100dd0 syscall: add wasip1 RandomGet
This function is needed starting with Go 1.24.
2025-02-25 14:41:42 +01:00
Ayke van Laethem 07c7eff3c3 runtime: add FIPS helper functions
Not entirely sure what they're for, but the Go runtime also stores this
information per goroutine so let's go with that.
2025-02-25 14:41:42 +01:00
Ayke van Laethem a1be8cd9fe machine/usb/descriptor: avoid bytes package
We can't use the bytes package in Go 1.24 since it would result in an
import cycle. Therefore, use bytealg.Index instead.

(I'm not sure this code is correct - just searching for a range of bytes
seems brittle. But at least this commit shouldn't change the code).
2025-02-25 14:41:42 +01:00
Ayke van Laethem 52b9fcd57f machine: remove bytes package dependency in flash code
This also moves flash padding code to a single place, since it was
copied 5 times.

This change is necessary in Go 1.24 to avoid an import cycle.
2025-02-25 14:41:42 +01:00
Ayke van Laethem ea53ace270 cgo: mangle identifier names
This mangles CGo identifier names to something like "_Cgo_foo" instead
of using literal identifiers like "C.foo". This works around
https://github.com/golang/go/issues/71777.

I don't like this solution, but I hope we'll find a better solution in
the future. In that case we can revert this commit.
2025-02-25 14:41:42 +01:00
Ayke van Laethem a6cd072fa1 Revert "fix: implement testing {Skip,Fail}Now"
This reverts commit c5879c682c.

It doesn't look like this is working (see
https://github.com/tinygo-org/tinygo/pull/4736#issuecomment-2679670226),
and it doesn't have any tests anyway to prove that it does work. So I
think it's best to revert it for now and add a working implementation
with tests in the future.
2025-02-25 12:38:52 +01:00
Ayke van Laethem 4372dbdd41 ci: use older image for cross-compiling builds
This ensures that the resulting binaries are compatible with a wide
range of Linux systems, not just the most recent ones.
2025-02-24 19:22:27 +01:00
deadprogram 17bb1fec44 feature: add buildmode=wasi-legacy to support existing base of users who expected the
older behavior for wasi modules to not return an exit code as if they were reactors.

See #4726 for some details on what this is intended to address.

Signed-off-by: deadprogram <ron@hybridgroup.com>
2025-02-21 13:06:14 +01:00
Ayke van Laethem f4fd79f7be runtime: manually initialize xorshift state
This ensures:

 1. The xorshift state is initialized during interp.
 2. The xorshift state gets initialized to a real random number on
    hardware that supports it at runtime.

This fixes a big binary size regression from the previous commit. It's
still not perfect: most programs increase binary size by a few bytes.
But it's not nearly as bad as before.
2025-02-21 11:36:17 +01:00
Ayke van Laethem 811b13a9d3 interp: correctly mark functions as modifying memory
Previously, if a function couldn't be interpreted in the interp pass, it
would just be run at runtime and the parameters would be marked as
potentially being modified. However, this is incorrect: the function
itself can also modify memory. So the function itself also needs to be
marked (recursively).

This fixes a number of regressions while upgrading to Go 1.24.

This results in a significant size regression that is mostly worked
around in the next commit.
2025-02-21 11:36:17 +01:00
Ron Evans 6e97079367 target: add Pimoroni Pico Plus2 (#4735)
* machine: separate definitions for ADC pins on rp2350/rp2350b

Signed-off-by: deadprogram <ron@hybridgroup.com>

* targets: add support for Pimoroni Pico Plus2

Signed-off-by: deadprogram <ron@hybridgroup.com>

---------

Signed-off-by: deadprogram <ron@hybridgroup.com>
Co-authored-by: Patricio Whittingslow <graded.sp@gmail.com>
2025-02-21 09:56:52 +01:00
soypat 9c7bbce029 rp2350: add pll generalized solution; fix ADC handles; pwm period fix 2025-02-21 09:56:52 +01:00
soypat 0ec1cb1e19 machine/rp2350: extending support to include the rp2350b 2025-02-21 09:56:52 +01:00
Scott Feldman e7118e5bda add comboat_fw tag for elecrow W5 boards with Combo-AT Wifi firmware 2025-02-21 07:22:17 +01:00
Ron Evans 150d9d1c6b fix: correctly handle id lookup for finalizeRef call
Modify the ID used for looking up the reference, based on suggestion made by @prochac

Also use console.error in the caase that the reference is not found, since it is now actually
known to be an error.
2025-02-20 22:17:38 +01:00
Laurent Demailly 8fe039156b fix: Avoid total failure on wasm finalizer call 2025-02-20 22:17:38 +01:00
leongross 2d17dec7bf os/file: add file.Chmod
Signed-off-by: leongross <leon.gross@9elements.com>
2025-02-19 22:12:51 +01:00
JP Hastings-Spital c1b267a208 Ensure build output directory is created
`tinygo build -o /path/to/out .` expected `/path/to/out` to already exist, which is different behaviour to `go build`. This change ensures tinygo creates any directories needed to be able to build to the specified output dir.
2025-02-19 19:55:48 +01:00
deadprogram f02c56c9e0 net: update to latest submodule with httptest subpackage and
ResolveIPAddress implementation.

Signed-off-by: deadprogram <ron@hybridgroup.com>
2025-02-17 13:16:56 +01:00
leongross c5879c682c fix: implement testing {Skip,Fail}Now
PR https://github.com/tinygo-org/tinygo/pull/4623 implements
runtime.GoExit() with which we can improve the testing package
and align it more to upstream testing behavour https://cs.opensource.google/go/go/+/refs/tags/go1.24.0:src/testing/testing.go;l=1150

Signed-off-by: leongross <leon.gross@9elements.com>
2025-02-15 21:30:22 +01:00
deadprogram 190c20825f targets: turn on GC for TKey1 device, since it does in fact work
Signed-off-by: deadprogram <ron@hybridgroup.com>
2025-02-14 12:49:20 +01:00
deadprogram d04eea7185 fix: add NoSandbox flag to chrome headless that is run during WASM tests, since
this is now required for Ubuntu 23+ and we are using Ubuntu 24+ when running
Github Actions.

See https://chromium.googlesource.com/chromium/src/+/main/docs/security/apparmor-userns-restrictions.md

Signed-off-by: deadprogram <ron@hybridgroup.com>
2025-02-12 17:13:56 +01:00
deadprogram f24cd31895 build: update Linux builds to run on ubuntu-latest since 20.04 is being retired
Signed-off-by: deadprogram <ron@hybridgroup.com>
2025-02-12 17:13:56 +01:00
m00874241 2044f6fbcc Added VersionTLS constants and VersionName(version uint16) method that turns it into a string, copied from big go 2025-01-30 07:30:57 +01:00
HattoriHanzo031 d55a89f96a board: support for NRF51 HW-651 (#4712)
NRF51: Support for NRF51 HW-651 board
* smoketest
* removed redundant flash-method
* smoketest fix
* description and links
* link fix
2025-01-30 05:46:52 +01:00
Elias Naur 080a6648e9 targets: match Pico2 stack size to Pico
Took me a while to debug weird crashes after switching from Pico to
Pico2.
2025-01-26 17:04:04 +08:00
deadprogram ec0a142190 build: update wasmtime used for CI to 29.0.1 to fix issue with install during CI tests
Signed-off-by: deadprogram <ron@hybridgroup.com>
2025-01-23 17:56:02 +08:00
Yurii Soldak b7fcf6ad68 nrf: fix adc read near zero 2025-01-23 13:03:25 +08:00
97 changed files with 1899 additions and 666 deletions
+3 -3
View File
@@ -109,9 +109,9 @@ jobs:
# "make lint" fails before go 1.21 because internal/tools/go.mod specifies packages that require go 1.21
fmt-check: false
resource_class: large
test-llvm19-go123:
test-llvm19-go124:
docker:
- image: golang:1.23-bullseye
- image: golang:1.24-bullseye
steps:
- test-linux:
llvm: "19"
@@ -124,4 +124,4 @@ workflows:
# least the smoke tests still pass.
- test-llvm15-go119
# This tests LLVM 19 support when linking against system libraries.
- test-llvm19-go123
- test-llvm19-go124
+2 -2
View File
@@ -39,7 +39,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v5
with:
go-version: '1.23'
go-version: '1.24'
cache: true
- name: Restore LLVM source cache
uses: actions/cache/restore@v4
@@ -143,7 +143,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v5
with:
go-version: '1.23'
go-version: '1.24'
cache: true
- name: Build TinyGo (LLVM ${{ matrix.version }})
run: go install -tags=llvm${{ matrix.version }}
+11 -10
View File
@@ -18,7 +18,7 @@ jobs:
# statically linked binary.
runs-on: ubuntu-latest
container:
image: golang:1.23-alpine
image: golang:1.24-alpine
outputs:
version: ${{ steps.version.outputs.version }}
steps:
@@ -146,12 +146,12 @@ jobs:
- name: Install Go
uses: actions/setup-go@v5
with:
go-version: '1.23'
go-version: '1.24'
cache: true
- name: Install wasmtime
uses: bytecodealliance/actions/wasmtime/setup@v1
with:
version: "19.0.1"
version: "29.0.1"
- name: Install wasm-tools
uses: bytecodealliance/actions/wasm-tools/setup@v1
- name: Download release artifact
@@ -165,11 +165,12 @@ jobs:
ln -s ~/lib/tinygo/bin/tinygo ~/go/bin/tinygo
- run: make tinygo-test-wasip1-fast
- run: make tinygo-test-wasip2-fast
- run: make tinygo-test-wasm
- run: make smoketest
assert-test-linux:
# Run all tests that can run on Linux, with LLVM assertions enabled to catch
# potential bugs.
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -189,7 +190,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v5
with:
go-version: '1.23'
go-version: '1.24'
cache: true
- name: Install Node.js
uses: actions/setup-node@v4
@@ -198,7 +199,7 @@ jobs:
- name: Install wasmtime
uses: bytecodealliance/actions/wasmtime/setup@v1
with:
version: "19.0.1"
version: "29.0.1"
- name: Setup `wasm-tools`
uses: bytecodealliance/actions/wasm-tools/setup@v1
- name: Restore LLVM source cache
@@ -277,7 +278,7 @@ jobs:
run: make tinygo-test
- run: make smoketest
- run: make wasmtest
- run: make tinygo-baremetal
- run: make tinygo-test-baremetal
build-linux-cross:
# Build ARM Linux binaries, ready for release.
# This intentionally uses an older Linux image, so that we compile against
@@ -297,7 +298,7 @@ jobs:
- goarch: arm
toolchain: arm-linux-gnueabihf
libc: armhf
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04 # note: use the oldest image available! (see above)
needs: build-linux
steps:
- name: Checkout
@@ -315,7 +316,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v5
with:
go-version: '1.23'
go-version: '1.24'
cache: true
- name: Restore LLVM source cache
uses: actions/cache/restore@v4
@@ -346,7 +347,7 @@ jobs:
uses: actions/cache/restore@v4
id: cache-llvm-build
with:
key: llvm-build-19-linux-${{ matrix.goarch }}-v2
key: llvm-build-19-linux-${{ matrix.goarch }}-v3
path: llvm-build
- name: Build LLVM
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
+1
View File
@@ -11,6 +11,7 @@ name: LLVM
on:
push:
branches: [ build-llvm-image ]
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
+6 -6
View File
@@ -41,7 +41,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v5
with:
go-version: '1.23'
go-version: '1.24'
cache: true
- name: Restore cached LLVM source
uses: actions/cache/restore@v4
@@ -109,7 +109,7 @@ jobs:
C:/Users/runneradmin/go/pkg/mod
- name: Install wasmtime
run: |
scoop install wasmtime@14.0.4
scoop install wasmtime@29.0.1
- name: make gen-device
run: make -j3 gen-device
- name: Test TinyGo
@@ -156,7 +156,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v5
with:
go-version: '1.23'
go-version: '1.24'
cache: true
- name: Download TinyGo build
uses: actions/download-artifact@v4
@@ -186,7 +186,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v5
with:
go-version: '1.23'
go-version: '1.24'
cache: true
- name: Download TinyGo build
uses: actions/download-artifact@v4
@@ -216,13 +216,13 @@ jobs:
- name: Install Dependencies
shell: bash
run: |
scoop install binaryen && scoop install wasmtime@14.0.4
scoop install binaryen && scoop install wasmtime@29.0.1
- name: Checkout
uses: actions/checkout@v4
- name: Install Go
uses: actions/setup-go@v5
with:
go-version: '1.23'
go-version: '1.24'
cache: true
- name: Download TinyGo build
uses: actions/download-artifact@v4
+69
View File
@@ -1,3 +1,72 @@
0.36.0
---
* **general**
- add initial Go 1.24 support
- add support for LLVM 19
- update license for 2025
- make small corrections for README regarding wasm
- use GOOS and GOARCH for building wasm simulated boards
- only infer target for wasm when GOOS and GOARCH are set correctly, not just based on file extension
- add test-corpus-wasip2
- use older image for cross-compiling builds
- update Linux builds to run on ubuntu-latest since 20.04 is being retired
- ensure build output directory is created
- add NoSandbox flag to chrome headless that is run during WASM tests, since this is now required for Ubuntu 23+ and we are using Ubuntu 24+ when running Github Actions
- update wasmtime used for CI to 29.0.1 to fix issue with install during CI tests
- update to use `Get-CimInstance` as `wmic` is being deprecated on WIndows
- remove unnecessary executable permissions
- `goenv`: update to new v0.36.0 development version
* **compiler**
- `builder`: fix parsing of external ld.lld error messages
- `cgo`: mangle identifier names
- `interp`: correctly mark functions as modifying memory
- add buildmode=wasi-legacy to support existing base of users who expected the older behavior for wasi modules to not return an exit code as if they were reactors
* **standard library**
- `crypto/tls`: add Dialer.DialContext() to fix websocket client
- `crypto/tls`: add VersionTLS constants and VersionName(version uint16) method that turns it into a string, copied from big go
- `internal/syscall/unix`: use our own version of this package
- `machine`: replace hard-coded cpu frequencies on rp2xxx
- `machine`: bump rp2350 CPUFrequency to 150 MHz
- `machine`: compute rp2 clock dividers from crystal and target frequency
- `machine`: remove bytes package dependency in flash code
- `machine/usb/descriptor`: avoid bytes package
- `net`: update to latest submodule with httptest subpackage and ResolveIPAddress implementation
- `os`: add File.Chdir support
- `os`: implement stub Chdir for non-OS systems
- `os/file`: add file.Chmod
- `reflect`: implement Value.Equal
- `runtime`: add FIPS helper functions
- `runtime`: manually initialize xorshift state
- `sync`: move Mutex to internal/task
- `syscall`: add wasip1 RandomGet
- `testing`: add Chdir
- `wasip2`: add stubs to get internal/syscall/unix to work
* **fixes**
- correctly handle calls for GetRNG() when being made from nrf devices with SoftDevice enabled
- fix stm32f103 ADC
- `wasm`: correctly handle id lookup for finalizeRef call
- `wasm`: avoid total failure on wasm finalizer call
- `wasm`: convert offset as signed int into unsigned int in syscall/js.stringVal in wasm_exec.js
* **targets**
- rp2350: add pll generalized solution; fix ADC handles; pwm period fix
- rp2350: extending support to include the rp2350b
- rp2350: cleanup: unexport internal USB and clock package variable, consts and types
- nrf: make ADC resolution changeable
- turn on GC for TKey1 device, since it does in fact work
- match Pico2 stack size to Pico
* **boards**
- add support for Pimoroni Pico Plus2
- add target for pico2-w board
- add comboat_fw tag for elecrow W5 boards with Combo-AT Wifi firmware
- add support for Elecrow Pico rp2350 W5 boards
- add support for Elecrow Pico rp2040 W5 boards
- add support for NRF51 HW-651
- add support for esp32c3-supermini
- add support for waveshare-rp2040-tiny
* **examples**
- add naive debouncing for pininterrupt example
0.35.0
---
* **general**
+2 -2
View File
@@ -1,5 +1,5 @@
# tinygo-llvm stage obtains the llvm source for TinyGo
FROM golang:1.23 AS tinygo-llvm
FROM golang:1.24 AS tinygo-llvm
RUN apt-get update && \
apt-get install -y apt-utils make cmake clang-15 ninja-build && \
@@ -33,7 +33,7 @@ RUN cd /tinygo/ && \
# tinygo-compiler copies the compiler build over to a base Go container (without
# all the build tools etc).
FROM golang:1.23 AS tinygo-compiler
FROM golang:1.24 AS tinygo-compiler
# Copy tinygo build.
COPY --from=tinygo-compiler-build /tinygo/build/release/tinygo /tinygo
+67 -23
View File
@@ -309,11 +309,9 @@ TEST_PACKAGES_FAST = \
container/heap \
container/list \
container/ring \
crypto/des \
crypto/ecdsa \
crypto/elliptic \
crypto/md5 \
crypto/rc4 \
crypto/sha1 \
crypto/sha256 \
crypto/sha512 \
@@ -355,17 +353,11 @@ TEST_PACKAGES_FAST = \
unique \
$(nil)
# Assume this will go away before Go2, so only check minor version.
ifeq ($(filter $(shell $(GO) env GOVERSION | cut -f 2 -d.), 16 17 18), )
TEST_PACKAGES_FAST += crypto/internal/nistec/fiat
else
TEST_PACKAGES_FAST += crypto/elliptic/internal/fiat
endif
# archive/zip requires os.ReadAt, which is not yet supported on windows
# bytes requires mmap
# compress/flate appears to hang on wasi
# crypto/aes fails on wasi, needs panic()/recover()
# crypto/des fails on wasi, needs panic()/recover()
# crypto/hmac fails on wasi, it exits with a "slice out of range" panic
# debug/plan9obj requires os.ReadAt, which is not yet supported on windows
# image requires recover(), which is not yet supported on wasi
@@ -386,6 +378,7 @@ TEST_PACKAGES_LINUX := \
archive/zip \
compress/flate \
crypto/aes \
crypto/des \
crypto/hmac \
debug/dwarf \
debug/plan9obj \
@@ -405,14 +398,52 @@ TEST_PACKAGES_LINUX := \
TEST_PACKAGES_DARWIN := $(TEST_PACKAGES_LINUX)
# os/user requires t.Skip() support
TEST_PACKAGES_WINDOWS := \
compress/flate \
crypto/des \
crypto/hmac \
os/user \
strconv \
text/template/parse \
$(nil)
# These packages cannot be tested on wasm, mostly because these tests assume a
# working filesystem. This could perhaps be fixed, by supporting filesystem
# access when running inside Node.js.
TEST_PACKAGES_WASM = $(filter-out $(TEST_PACKAGES_NONWASM), $(TEST_PACKAGES_FAST))
TEST_PACKAGES_NONWASM = \
compress/lzw \
compress/zlib \
crypto/ecdsa \
debug/macho \
embed/internal/embedtest \
go/format \
os \
testing \
$(nil)
# These packages cannot be tested on baremetal.
#
# Some reasons why the tests don't pass on baremetal:
#
# * No filesystem is available, so packages like compress/zlib can't be tested
# (just like wasm).
# * picolibc math functions apparently are less precise, the math package
# fails on baremetal.
# * Some packages fail or hang for an unknown reason, this should be
# investigated and fixed.
TEST_PACKAGES_BAREMETAL = $(filter-out $(TEST_PACKAGES_NONBAREMETAL), $(TEST_PACKAGES_FAST))
TEST_PACKAGES_NONBAREMETAL = \
$(TEST_PACKAGES_NONWASM) \
crypto/elliptic \
math \
reflect \
encoding/asn1 \
encoding/base32 \
go/ast \
$(nil)
# Report platforms on which each standard library package is known to pass tests
jointmp := $(shell echo /tmp/join.$$$$)
report-stdlib-tests-pass:
@@ -456,6 +487,8 @@ tinygo-bench-fast:
$(TINYGO) test -bench . $(TEST_PACKAGES_HOST)
# Same thing, except for wasi rather than the current platform.
tinygo-test-wasm:
$(TINYGO) test -target wasm $(TEST_PACKAGES_WASM)
tinygo-test-wasi:
$(TINYGO) test -target wasip1 $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW) ./tests/runtime_wasi
tinygo-test-wasip1:
@@ -490,6 +523,10 @@ tinygo-bench-wasip2:
tinygo-bench-wasip2-fast:
$(TINYGO) test -target wasip2 -bench . $(TEST_PACKAGES_FAST)
# Run tests on riscv-qemu since that one provides a large amount of memory.
tinygo-test-baremetal:
$(TINYGO) test -target riscv-qemu $(TEST_PACKAGES_BAREMETAL)
# Test external packages in a large corpus.
test-corpus:
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test $(GOTESTFLAGS) -timeout=1h -buildmode exe -tags byollvm -run TestCorpus . -corpus=testdata/corpus.yaml
@@ -497,11 +534,8 @@ test-corpus-fast:
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test $(GOTESTFLAGS) -timeout=1h -buildmode exe -tags byollvm -run TestCorpus -short . -corpus=testdata/corpus.yaml
test-corpus-wasi: wasi-libc
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test $(GOTESTFLAGS) -timeout=1h -buildmode exe -tags byollvm -run TestCorpus . -corpus=testdata/corpus.yaml -target=wasip1
tinygo-baremetal:
# Regression tests that run on a baremetal target and don't fit in either main_test.go or smoketest.
# regression test for #2666: e.g. encoding/hex must pass on baremetal
$(TINYGO) test -target cortex-m-qemu encoding/hex
test-corpus-wasip2: wasi-libc
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test $(GOTESTFLAGS) -timeout=1h -buildmode exe -tags byollvm -run TestCorpus . -corpus=testdata/corpus.yaml -target=wasip2
.PHONY: testchdir
testchdir:
@@ -523,6 +557,8 @@ smoketest: testchdir
# regression test for #2563
cd tests/os/smoke && $(TINYGO) test -c -target=pybadge && rm smoke.test
# test all examples (except pwm)
$(TINYGO) build -size short -o test.hex -target=pga2350 examples/echo
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=pca10040 examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=pca10040 examples/adc
@@ -571,21 +607,23 @@ smoketest: testchdir
@$(MD5SUM) test.hex
# test simulated boards on play.tinygo.org
ifneq ($(WASM), 0)
$(TINYGO) build -size short -o test.wasm -tags=arduino examples/blinky1
GOOS=js GOARCH=wasm $(TINYGO) build -size short -o test.wasm -tags=arduino examples/blinky1
@$(MD5SUM) test.wasm
$(TINYGO) build -size short -o test.wasm -tags=hifive1b examples/blinky1
GOOS=js GOARCH=wasm $(TINYGO) build -size short -o test.wasm -tags=hifive1b examples/blinky1
@$(MD5SUM) test.wasm
$(TINYGO) build -size short -o test.wasm -tags=reelboard examples/blinky1
GOOS=js GOARCH=wasm $(TINYGO) build -size short -o test.wasm -tags=reelboard examples/blinky1
@$(MD5SUM) test.wasm
$(TINYGO) build -size short -o test.wasm -tags=microbit examples/microbit-blink
GOOS=js GOARCH=wasm $(TINYGO) build -size short -o test.wasm -tags=microbit examples/microbit-blink
@$(MD5SUM) test.wasm
$(TINYGO) build -size short -o test.wasm -tags=circuitplay_express examples/blinky1
GOOS=js GOARCH=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
GOOS=js GOARCH=wasm $(TINYGO) build -size short -o test.wasm -tags=circuitplay_bluefruit examples/blinky1
@$(MD5SUM) test.wasm
$(TINYGO) build -size short -o test.wasm -tags=mch2022 examples/machinetest
GOOS=js GOARCH=wasm $(TINYGO) build -size short -o test.wasm -tags=mch2022 examples/machinetest
@$(MD5SUM) test.wasm
$(TINYGO) build -size short -o test.wasm -tags=gopher_badge examples/blinky1
GOOS=js GOARCH=wasm $(TINYGO) build -size short -o test.wasm -tags=gopher_badge examples/blinky1
@$(MD5SUM) test.wasm
GOOS=js GOARCH=wasm $(TINYGO) build -size short -o test.wasm -tags=pico examples/blinky1
@$(MD5SUM) test.wasm
endif
# test all targets/boards
@@ -745,6 +783,8 @@ endif
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=tiny2350 examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=pico-plus2 examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=waveshare-rp2040-tiny examples/echo
@$(MD5SUM) test.hex
# test pwm
@@ -867,6 +907,10 @@ endif
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=elecrow-rp2350 examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=hw-651 examples/machinetest
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=hw-651-s110v8 examples/machinetest
@$(MD5SUM) test.hex
ifneq ($(WASM), 0)
$(TINYGO) build -size short -o wasm.wasm -target=wasm examples/wasm/export
$(TINYGO) build -size short -o wasm.wasm -target=wasm examples/wasm/main
+2 -2
View File
@@ -1,7 +1,7 @@
Copyright (c) 2018-2023 The TinyGo Authors. All rights reserved.
Copyright (c) 2018-2025 The TinyGo Authors. All rights reserved.
TinyGo includes portions of the Go standard library.
Copyright (c) 2009-2023 The Go Authors. All rights reserved.
Copyright (c) 2009-2024 The Go Authors. All rights reserved.
TinyGo includes portions of LLVM, which is under the Apache License v2.0 with
LLVM Exceptions. See https://llvm.org/LICENSE.txt for license information.
+9 -7
View File
@@ -48,20 +48,22 @@ Here is a small TinyGo program for use by a WASI host application:
```go
package main
//go:wasm-module yourmodulename
//export add
//go:wasmexport add
func add(x, y uint32) uint32 {
return x + y
}
// main is required for the `wasip1` target, even if it isn't used.
func main() {}
```
This compiles the above TinyGo program for use on any WASI runtime:
This compiles the above TinyGo program for use on any WASI Preview 1 runtime:
```shell
tinygo build -o main.wasm -target=wasip1 main.go
tinygo build -buildmode=c-shared -o add.wasm -target=wasip1 add.go
```
You can also use the same syntax as Go 1.24+:
```shell
GOARCH=wasip1 GOOS=wasm tinygo build -buildmode=c-shared -o add.wasm add.go
```
## Installation
+15
View File
@@ -604,6 +604,11 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
},
}
// Create the output directory, if needed
if err := os.MkdirAll(filepath.Dir(outpath), 0777); err != nil {
return result, err
}
// Check whether we only need to create an object file.
// If so, we don't need to link anything and will be finished quickly.
outext := filepath.Ext(outpath)
@@ -667,6 +672,16 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
ldflags = append(ldflags, "--no-entry")
}
if config.Options.BuildMode == "wasi-legacy" {
if !strings.HasPrefix(config.Triple(), "wasm32-") {
return result, fmt.Errorf("buildmode wasi-legacy is only supported on wasm")
}
if config.Options.Scheduler != "none" {
return result, fmt.Errorf("buildmode wasi-legacy only supports scheduler=none")
}
}
// Add compiler-rt dependency if needed. Usually this is a simple load from
// a cache.
if config.Target.RTLib == "compiler-rt" {
-1
View File
@@ -69,7 +69,6 @@ func TestClangAttributes(t *testing.T) {
{GOOS: "darwin", GOARCH: "arm64"},
{GOOS: "windows", GOARCH: "amd64"},
{GOOS: "windows", GOARCH: "arm64"},
{GOOS: "wasip1", GOARCH: "wasm"},
} {
name := "GOOS=" + options.GOOS + ",GOARCH=" + options.GOARCH
if options.GOARCH == "arm" {
+2 -2
View File
@@ -26,7 +26,7 @@ func NewConfig(options *compileopts.Options) (*compileopts.Config, error) {
// Version range supported by TinyGo.
const minorMin = 19
const minorMax = 23
const minorMax = 24
// Check that we support this Go toolchain version.
gorootMajor, gorootMinor, err := goenv.GetGorootVersion()
@@ -36,7 +36,7 @@ func NewConfig(options *compileopts.Options) (*compileopts.Config, error) {
if gorootMajor != 1 || gorootMinor < minorMin || gorootMinor > minorMax {
// Note: when this gets updated, also update the Go compatibility matrix:
// https://github.com/tinygo-org/tinygo-site/blob/dev/content/docs/reference/go-compat-matrix.md
return nil, fmt.Errorf("requires go version 1.19 through 1.23, got go%d.%d", gorootMajor, gorootMinor)
return nil, fmt.Errorf("requires go version 1.%d through 1.%d, got go%d.%d", minorMin, minorMax, gorootMajor, gorootMinor)
}
// Check that the Go toolchain version isn't too new, if we haven't been
+2 -2
View File
@@ -43,8 +43,8 @@ func TestBinarySize(t *testing.T) {
tests := []sizeTest{
// microcontrollers
{"hifive1b", "examples/echo", 4560, 280, 0, 2268},
{"microbit", "examples/serial", 2908, 388, 8, 2272},
{"wioterminal", "examples/pininterrupt", 7293, 1487, 116, 6912},
{"microbit", "examples/serial", 2916, 388, 8, 2272},
{"wioterminal", "examples/pininterrupt", 7359, 1489, 116, 6912},
// TODO: also check wasm. Right now this is difficult, because
// wasm binaries are run through wasm-opt and therefore the
+45 -64
View File
@@ -92,18 +92,18 @@ type noescapingFunc struct {
// cgoAliases list type aliases between Go and C, for types that are equivalent
// in both languages. See addTypeAliases.
var cgoAliases = map[string]string{
"C.int8_t": "int8",
"C.int16_t": "int16",
"C.int32_t": "int32",
"C.int64_t": "int64",
"C.uint8_t": "uint8",
"C.uint16_t": "uint16",
"C.uint32_t": "uint32",
"C.uint64_t": "uint64",
"C.uintptr_t": "uintptr",
"C.float": "float32",
"C.double": "float64",
"C._Bool": "bool",
"_Cgo_int8_t": "int8",
"_Cgo_int16_t": "int16",
"_Cgo_int32_t": "int32",
"_Cgo_int64_t": "int64",
"_Cgo_uint8_t": "uint8",
"_Cgo_uint16_t": "uint16",
"_Cgo_uint32_t": "uint32",
"_Cgo_uint64_t": "uint64",
"_Cgo_uintptr_t": "uintptr",
"_Cgo_float": "float32",
"_Cgo_double": "float64",
"_Cgo__Bool": "bool",
}
// builtinAliases are handled specially because they only exist on the Go side
@@ -145,48 +145,46 @@ typedef unsigned long long _Cgo_ulonglong;
// The string/bytes functions below implement C.CString etc. To make sure the
// runtime doesn't need to know the C int type, lengths are converted to uintptr
// first.
// These functions will be modified to get a "C." prefix, so the source below
// doesn't reflect the final AST.
const generatedGoFilePrefixBase = `
import "syscall"
import "unsafe"
var _ unsafe.Pointer
//go:linkname C.CString runtime.cgo_CString
func CString(string) *C.char
//go:linkname _Cgo_CString runtime.cgo_CString
func _Cgo_CString(string) *_Cgo_char
//go:linkname C.GoString runtime.cgo_GoString
func GoString(*C.char) string
//go:linkname _Cgo_GoString runtime.cgo_GoString
func _Cgo_GoString(*_Cgo_char) string
//go:linkname C.__GoStringN runtime.cgo_GoStringN
func __GoStringN(*C.char, uintptr) string
//go:linkname _Cgo___GoStringN runtime.cgo_GoStringN
func _Cgo___GoStringN(*_Cgo_char, uintptr) string
func GoStringN(cstr *C.char, length C.int) string {
return C.__GoStringN(cstr, uintptr(length))
func _Cgo_GoStringN(cstr *_Cgo_char, length _Cgo_int) string {
return _Cgo___GoStringN(cstr, uintptr(length))
}
//go:linkname C.__GoBytes runtime.cgo_GoBytes
func __GoBytes(unsafe.Pointer, uintptr) []byte
//go:linkname _Cgo___GoBytes runtime.cgo_GoBytes
func _Cgo___GoBytes(unsafe.Pointer, uintptr) []byte
func GoBytes(ptr unsafe.Pointer, length C.int) []byte {
return C.__GoBytes(ptr, uintptr(length))
func _Cgo_GoBytes(ptr unsafe.Pointer, length _Cgo_int) []byte {
return _Cgo___GoBytes(ptr, uintptr(length))
}
//go:linkname C.__CBytes runtime.cgo_CBytes
func __CBytes([]byte) unsafe.Pointer
//go:linkname _Cgo___CBytes runtime.cgo_CBytes
func _Cgo___CBytes([]byte) unsafe.Pointer
func CBytes(b []byte) unsafe.Pointer {
return C.__CBytes(b)
func _Cgo_CBytes(b []byte) unsafe.Pointer {
return _Cgo___CBytes(b)
}
//go:linkname C.__get_errno_num runtime.cgo_errno
func __get_errno_num() uintptr
//go:linkname _Cgo___get_errno_num runtime.cgo_errno
func _Cgo___get_errno_num() uintptr
`
const generatedGoFilePrefixOther = generatedGoFilePrefixBase + `
func __get_errno() error {
return syscall.Errno(C.__get_errno_num())
func _Cgo___get_errno() error {
return syscall.Errno(_Cgo___get_errno_num())
}
`
@@ -197,7 +195,7 @@ func __get_errno() error {
// map the errno values to match the values in the syscall package.
// Source of the errno values: lib/mingw-w64/mingw-w64-headers/crt/errno.h
const generatedGoFilePrefixWindows = generatedGoFilePrefixBase + `
var __errno_mapping = [...]syscall.Errno{
var _Cgo___errno_mapping = [...]syscall.Errno{
1: syscall.EPERM,
2: syscall.ENOENT,
3: syscall.ESRCH,
@@ -238,10 +236,10 @@ var __errno_mapping = [...]syscall.Errno{
42: syscall.EILSEQ,
}
func __get_errno() error {
num := C.__get_errno_num()
if num < uintptr(len(__errno_mapping)) {
if mapped := __errno_mapping[num]; mapped != 0 {
func _Cgo___get_errno() error {
num := _Cgo___get_errno_num()
if num < uintptr(len(_Cgo___errno_mapping)) {
if mapped := _Cgo___errno_mapping[num]; mapped != 0 {
return mapped
}
}
@@ -304,23 +302,6 @@ func Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cfl
// If the Comments field is not set to nil, the go/format package will get
// confused about where comments should go.
p.generated.Comments = nil
// Adjust some of the functions in there.
for _, decl := range p.generated.Decls {
switch decl := decl.(type) {
case *ast.FuncDecl:
switch decl.Name.Name {
case "CString", "GoString", "GoStringN", "__GoStringN", "GoBytes", "__GoBytes", "CBytes", "__CBytes", "__get_errno_num", "__get_errno", "__errno_mapping":
// Adjust the name to have a "C." prefix so it is correctly
// resolved.
decl.Name.Name = "C." + decl.Name.Name
}
}
}
// Patch some types, for example *C.char in C.CString.
cf := p.newCGoFile(nil, -1) // dummy *cgoFile for the walker
astutil.Apply(p.generated, func(cursor *astutil.Cursor) bool {
return cf.walker(cursor, nil)
}, nil)
// Find `import "C"` C fragments in the file.
p.cgoHeaders = make([]string, len(files)) // combined CGo header fragment for each file
@@ -399,7 +380,7 @@ func Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cfl
Tok: token.TYPE,
}
for _, name := range builtinAliases {
typeSpec := p.getIntegerType("C."+name, names["_Cgo_"+name])
typeSpec := p.getIntegerType("_Cgo_"+name, names["_Cgo_"+name])
gen.Specs = append(gen.Specs, typeSpec)
}
p.generated.Decls = append(p.generated.Decls, gen)
@@ -1272,7 +1253,7 @@ func (p *cgoPackage) getUnnamedDeclName(prefix string, itf interface{}) string {
func (f *cgoFile) getASTDeclName(name string, found clangCursor, iscall bool) string {
// Some types are defined in stdint.h and map directly to a particular Go
// type.
if alias := cgoAliases["C."+name]; alias != "" {
if alias := cgoAliases["_Cgo_"+name]; alias != "" {
return alias
}
node := f.getASTDeclNode(name, found)
@@ -1282,7 +1263,7 @@ func (f *cgoFile) getASTDeclName(name string, found clangCursor, iscall bool) st
}
return node.Name.Name
}
return "C." + name
return "_Cgo_" + name
}
// getASTDeclNode will declare the given C AST node (if not already defined) and
@@ -1382,8 +1363,8 @@ extern __typeof(%s) %s __attribute__((alias(%#v)));
case *elaboratedTypeInfo:
// Add struct bitfields.
for _, bitfield := range elaboratedType.bitfields {
f.createBitfieldGetter(bitfield, "C."+name)
f.createBitfieldSetter(bitfield, "C."+name)
f.createBitfieldGetter(bitfield, "_Cgo_"+name)
f.createBitfieldSetter(bitfield, "_Cgo_"+name)
}
if elaboratedType.unionSize != 0 {
// Create union getters/setters.
@@ -1392,7 +1373,7 @@ extern __typeof(%s) %s __attribute__((alias(%#v)));
f.addError(elaboratedType.pos, fmt.Sprintf("union must have field with a single name, it has %d names", len(field.Names)))
continue
}
f.createUnionAccessor(field, "C."+name)
f.createUnionAccessor(field, "_Cgo_"+name)
}
}
}
@@ -1441,7 +1422,7 @@ func (f *cgoFile) walker(cursor *astutil.Cursor, names map[string]clangCursor) b
node.Rhs = append(node.Rhs, &ast.CallExpr{
Fun: &ast.Ident{
NamePos: node.Lhs[1].End(),
Name: "C.__get_errno",
Name: "_Cgo___get_errno",
},
})
}
@@ -1466,7 +1447,7 @@ func (f *cgoFile) walker(cursor *astutil.Cursor, names map[string]clangCursor) b
return true
}
if x.Name == "C" {
name := "C." + node.Sel.Name
name := "_Cgo_" + node.Sel.Name
if found, ok := names[node.Sel.Name]; ok {
name = f.getASTDeclName(node.Sel.Name, found, false)
}
+27 -27
View File
@@ -219,7 +219,7 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) {
numArgs := int(C.tinygo_clang_Cursor_getNumArguments(c))
obj := &ast.Object{
Kind: ast.Fun,
Name: "C." + name,
Name: "_Cgo_" + name,
}
exportName := name
localName := name
@@ -257,7 +257,7 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) {
},
Name: &ast.Ident{
NamePos: pos,
Name: "C." + localName,
Name: "_Cgo_" + localName,
Obj: obj,
},
Type: &ast.FuncType{
@@ -319,7 +319,7 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) {
return decl, stringSignature
case C.CXCursor_StructDecl, C.CXCursor_UnionDecl:
typ := f.makeASTRecordType(c, pos)
typeName := "C." + name
typeName := "_Cgo_" + name
typeExpr := typ.typeExpr
if typ.unionSize != 0 {
// Convert to a single-field struct type.
@@ -340,7 +340,7 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) {
obj.Decl = typeSpec
return typeSpec, typ
case C.CXCursor_TypedefDecl:
typeName := "C." + name
typeName := "_Cgo_" + name
underlyingType := C.tinygo_clang_getTypedefDeclUnderlyingType(c)
obj := &ast.Object{
Kind: ast.Typ,
@@ -378,12 +378,12 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) {
}
obj := &ast.Object{
Kind: ast.Var,
Name: "C." + name,
Name: "_Cgo_" + name,
}
valueSpec := &ast.ValueSpec{
Names: []*ast.Ident{{
NamePos: pos,
Name: "C." + name,
Name: "_Cgo_" + name,
Obj: obj,
}},
Type: typeExpr,
@@ -407,12 +407,12 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) {
}
obj := &ast.Object{
Kind: ast.Con,
Name: "C." + name,
Name: "_Cgo_" + name,
}
valueSpec := &ast.ValueSpec{
Names: []*ast.Ident{{
NamePos: pos,
Name: "C." + name,
Name: "_Cgo_" + name,
Obj: obj,
}},
Values: []ast.Expr{expr},
@@ -423,7 +423,7 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) {
case C.CXCursor_EnumDecl:
obj := &ast.Object{
Kind: ast.Typ,
Name: "C." + name,
Name: "_Cgo_" + name,
}
underlying := C.tinygo_clang_getEnumDeclIntegerType(c)
// TODO: gc's CGo implementation uses types such as `uint32` for enums
@@ -431,7 +431,7 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) {
typeSpec := &ast.TypeSpec{
Name: &ast.Ident{
NamePos: pos,
Name: "C." + name,
Name: "_Cgo_" + name,
Obj: obj,
},
Assign: pos,
@@ -454,12 +454,12 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) {
}
obj := &ast.Object{
Kind: ast.Con,
Name: "C." + name,
Name: "_Cgo_" + name,
}
valueSpec := &ast.ValueSpec{
Names: []*ast.Ident{{
NamePos: pos,
Name: "C." + name,
Name: "_Cgo_" + name,
Obj: obj,
}},
Values: []ast.Expr{expr},
@@ -745,27 +745,27 @@ func (f *cgoFile) makeASTType(typ C.CXType, pos token.Pos) ast.Expr {
var typeName string
switch typ.kind {
case C.CXType_Char_S, C.CXType_Char_U:
typeName = "C.char"
typeName = "_Cgo_char"
case C.CXType_SChar:
typeName = "C.schar"
typeName = "_Cgo_schar"
case C.CXType_UChar:
typeName = "C.uchar"
typeName = "_Cgo_uchar"
case C.CXType_Short:
typeName = "C.short"
typeName = "_Cgo_short"
case C.CXType_UShort:
typeName = "C.ushort"
typeName = "_Cgo_ushort"
case C.CXType_Int:
typeName = "C.int"
typeName = "_Cgo_int"
case C.CXType_UInt:
typeName = "C.uint"
typeName = "_Cgo_uint"
case C.CXType_Long:
typeName = "C.long"
typeName = "_Cgo_long"
case C.CXType_ULong:
typeName = "C.ulong"
typeName = "_Cgo_ulong"
case C.CXType_LongLong:
typeName = "C.longlong"
typeName = "_Cgo_longlong"
case C.CXType_ULongLong:
typeName = "C.ulonglong"
typeName = "_Cgo_ulonglong"
case C.CXType_Bool:
typeName = "bool"
case C.CXType_Float, C.CXType_Double, C.CXType_LongDouble:
@@ -896,7 +896,7 @@ func (f *cgoFile) makeASTType(typ C.CXType, pos token.Pos) ast.Expr {
typeSpelling := getString(C.clang_getTypeSpelling(typ))
typeKindSpelling := getString(C.clang_getTypeKindSpelling(typ.kind))
f.addError(pos, fmt.Sprintf("unknown C type: %v (libclang type kind %s)", typeSpelling, typeKindSpelling))
typeName = "C.<unknown>"
typeName = "_Cgo_<unknown>"
}
return &ast.Ident{
NamePos: pos,
@@ -913,7 +913,7 @@ func (p *cgoPackage) getIntegerType(name string, cursor clangCursor) *ast.TypeSp
var goName string
typeSize := C.clang_Type_getSizeOf(underlyingType)
switch name {
case "C.char":
case "_Cgo_char":
if typeSize != 1 {
// This happens for some very special purpose architectures
// (DSPs etc.) that are not currently targeted.
@@ -926,7 +926,7 @@ func (p *cgoPackage) getIntegerType(name string, cursor clangCursor) *ast.TypeSp
case C.CXType_Char_U:
goName = "uint8"
}
case "C.schar", "C.short", "C.int", "C.long", "C.longlong":
case "_Cgo_schar", "_Cgo_short", "_Cgo_int", "_Cgo_long", "_Cgo_longlong":
switch typeSize {
case 1:
goName = "int8"
@@ -937,7 +937,7 @@ func (p *cgoPackage) getIntegerType(name string, cursor clangCursor) *ast.TypeSp
case 8:
goName = "int64"
}
case "C.uchar", "C.ushort", "C.uint", "C.ulong", "C.ulonglong":
case "_Cgo_uchar", "_Cgo_ushort", "_Cgo_uint", "_Cgo_ulong", "_Cgo_ulonglong":
switch typeSize {
case 1:
goName = "uint8"
+31 -31
View File
@@ -5,50 +5,50 @@ import "unsafe"
var _ unsafe.Pointer
//go:linkname C.CString runtime.cgo_CString
func C.CString(string) *C.char
//go:linkname _Cgo_CString runtime.cgo_CString
func _Cgo_CString(string) *_Cgo_char
//go:linkname C.GoString runtime.cgo_GoString
func C.GoString(*C.char) string
//go:linkname _Cgo_GoString runtime.cgo_GoString
func _Cgo_GoString(*_Cgo_char) string
//go:linkname C.__GoStringN runtime.cgo_GoStringN
func C.__GoStringN(*C.char, uintptr) string
//go:linkname _Cgo___GoStringN runtime.cgo_GoStringN
func _Cgo___GoStringN(*_Cgo_char, uintptr) string
func C.GoStringN(cstr *C.char, length C.int) string {
return C.__GoStringN(cstr, uintptr(length))
func _Cgo_GoStringN(cstr *_Cgo_char, length _Cgo_int) string {
return _Cgo___GoStringN(cstr, uintptr(length))
}
//go:linkname C.__GoBytes runtime.cgo_GoBytes
func C.__GoBytes(unsafe.Pointer, uintptr) []byte
//go:linkname _Cgo___GoBytes runtime.cgo_GoBytes
func _Cgo___GoBytes(unsafe.Pointer, uintptr) []byte
func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte {
return C.__GoBytes(ptr, uintptr(length))
func _Cgo_GoBytes(ptr unsafe.Pointer, length _Cgo_int) []byte {
return _Cgo___GoBytes(ptr, uintptr(length))
}
//go:linkname C.__CBytes runtime.cgo_CBytes
func C.__CBytes([]byte) unsafe.Pointer
//go:linkname _Cgo___CBytes runtime.cgo_CBytes
func _Cgo___CBytes([]byte) unsafe.Pointer
func C.CBytes(b []byte) unsafe.Pointer {
return C.__CBytes(b)
func _Cgo_CBytes(b []byte) unsafe.Pointer {
return _Cgo___CBytes(b)
}
//go:linkname C.__get_errno_num runtime.cgo_errno
func C.__get_errno_num() uintptr
//go:linkname _Cgo___get_errno_num runtime.cgo_errno
func _Cgo___get_errno_num() uintptr
func C.__get_errno() error {
return syscall.Errno(C.__get_errno_num())
func _Cgo___get_errno() error {
return syscall.Errno(_Cgo___get_errno_num())
}
type (
C.char uint8
C.schar int8
C.uchar uint8
C.short int16
C.ushort uint16
C.int int32
C.uint uint32
C.long int32
C.ulong uint32
C.longlong int64
C.ulonglong uint64
_Cgo_char uint8
_Cgo_schar int8
_Cgo_uchar uint8
_Cgo_short int16
_Cgo_ushort uint16
_Cgo_int int32
_Cgo_uint uint32
_Cgo_long int32
_Cgo_ulong uint32
_Cgo_longlong int64
_Cgo_ulonglong uint64
)
+38 -38
View File
@@ -5,58 +5,58 @@ import "unsafe"
var _ unsafe.Pointer
//go:linkname C.CString runtime.cgo_CString
func C.CString(string) *C.char
//go:linkname _Cgo_CString runtime.cgo_CString
func _Cgo_CString(string) *_Cgo_char
//go:linkname C.GoString runtime.cgo_GoString
func C.GoString(*C.char) string
//go:linkname _Cgo_GoString runtime.cgo_GoString
func _Cgo_GoString(*_Cgo_char) string
//go:linkname C.__GoStringN runtime.cgo_GoStringN
func C.__GoStringN(*C.char, uintptr) string
//go:linkname _Cgo___GoStringN runtime.cgo_GoStringN
func _Cgo___GoStringN(*_Cgo_char, uintptr) string
func C.GoStringN(cstr *C.char, length C.int) string {
return C.__GoStringN(cstr, uintptr(length))
func _Cgo_GoStringN(cstr *_Cgo_char, length _Cgo_int) string {
return _Cgo___GoStringN(cstr, uintptr(length))
}
//go:linkname C.__GoBytes runtime.cgo_GoBytes
func C.__GoBytes(unsafe.Pointer, uintptr) []byte
//go:linkname _Cgo___GoBytes runtime.cgo_GoBytes
func _Cgo___GoBytes(unsafe.Pointer, uintptr) []byte
func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte {
return C.__GoBytes(ptr, uintptr(length))
func _Cgo_GoBytes(ptr unsafe.Pointer, length _Cgo_int) []byte {
return _Cgo___GoBytes(ptr, uintptr(length))
}
//go:linkname C.__CBytes runtime.cgo_CBytes
func C.__CBytes([]byte) unsafe.Pointer
//go:linkname _Cgo___CBytes runtime.cgo_CBytes
func _Cgo___CBytes([]byte) unsafe.Pointer
func C.CBytes(b []byte) unsafe.Pointer {
return C.__CBytes(b)
func _Cgo_CBytes(b []byte) unsafe.Pointer {
return _Cgo___CBytes(b)
}
//go:linkname C.__get_errno_num runtime.cgo_errno
func C.__get_errno_num() uintptr
//go:linkname _Cgo___get_errno_num runtime.cgo_errno
func _Cgo___get_errno_num() uintptr
func C.__get_errno() error {
return syscall.Errno(C.__get_errno_num())
func _Cgo___get_errno() error {
return syscall.Errno(_Cgo___get_errno_num())
}
type (
C.char uint8
C.schar int8
C.uchar uint8
C.short int16
C.ushort uint16
C.int int32
C.uint uint32
C.long int32
C.ulong uint32
C.longlong int64
C.ulonglong uint64
_Cgo_char uint8
_Cgo_schar int8
_Cgo_uchar uint8
_Cgo_short int16
_Cgo_ushort uint16
_Cgo_int int32
_Cgo_uint uint32
_Cgo_long int32
_Cgo_ulong uint32
_Cgo_longlong int64
_Cgo_ulonglong uint64
)
const C.foo = 3
const C.bar = C.foo
const C.unreferenced = 4
const C.referenced = C.unreferenced
const C.fnlike_val = 5
const C.square_val = (20 * 20)
const C.add_val = (3 + 5)
const _Cgo_foo = 3
const _Cgo_bar = _Cgo_foo
const _Cgo_unreferenced = 4
const _Cgo_referenced = _Cgo_unreferenced
const _Cgo_fnlike_val = 5
const _Cgo_square_val = (20 * 20)
const _Cgo_add_val = (3 + 5)
+46 -46
View File
@@ -14,16 +14,16 @@
// testdata/errors.go:3:1: function "unusedFunction" in #cgo noescape line is not used
// Type checking errors after CGo processing:
// testdata/errors.go:102: cannot use 2 << 10 (untyped int constant 2048) as C.char value in variable declaration (overflows)
// testdata/errors.go:102: cannot use 2 << 10 (untyped int constant 2048) as _Cgo_char value in variable declaration (overflows)
// testdata/errors.go:105: unknown field z in struct literal
// testdata/errors.go:108: undefined: C.SOME_CONST_1
// testdata/errors.go:110: cannot use C.SOME_CONST_3 (untyped int constant 1234) as byte value in variable declaration (overflows)
// testdata/errors.go:112: undefined: C.SOME_CONST_4
// testdata/errors.go:114: undefined: C.SOME_CONST_b
// testdata/errors.go:116: undefined: C.SOME_CONST_startspace
// testdata/errors.go:119: undefined: C.SOME_PARAM_CONST_invalid
// testdata/errors.go:122: undefined: C.add_toomuch
// testdata/errors.go:123: undefined: C.add_toolittle
// testdata/errors.go:108: undefined: _Cgo_SOME_CONST_1
// testdata/errors.go:110: cannot use _Cgo_SOME_CONST_3 (untyped int constant 1234) as byte value in variable declaration (overflows)
// testdata/errors.go:112: undefined: _Cgo_SOME_CONST_4
// testdata/errors.go:114: undefined: _Cgo_SOME_CONST_b
// testdata/errors.go:116: undefined: _Cgo_SOME_CONST_startspace
// testdata/errors.go:119: undefined: _Cgo_SOME_PARAM_CONST_invalid
// testdata/errors.go:122: undefined: _Cgo_add_toomuch
// testdata/errors.go:123: undefined: _Cgo_add_toolittle
package main
@@ -32,58 +32,58 @@ import "unsafe"
var _ unsafe.Pointer
//go:linkname C.CString runtime.cgo_CString
func C.CString(string) *C.char
//go:linkname _Cgo_CString runtime.cgo_CString
func _Cgo_CString(string) *_Cgo_char
//go:linkname C.GoString runtime.cgo_GoString
func C.GoString(*C.char) string
//go:linkname _Cgo_GoString runtime.cgo_GoString
func _Cgo_GoString(*_Cgo_char) string
//go:linkname C.__GoStringN runtime.cgo_GoStringN
func C.__GoStringN(*C.char, uintptr) string
//go:linkname _Cgo___GoStringN runtime.cgo_GoStringN
func _Cgo___GoStringN(*_Cgo_char, uintptr) string
func C.GoStringN(cstr *C.char, length C.int) string {
return C.__GoStringN(cstr, uintptr(length))
func _Cgo_GoStringN(cstr *_Cgo_char, length _Cgo_int) string {
return _Cgo___GoStringN(cstr, uintptr(length))
}
//go:linkname C.__GoBytes runtime.cgo_GoBytes
func C.__GoBytes(unsafe.Pointer, uintptr) []byte
//go:linkname _Cgo___GoBytes runtime.cgo_GoBytes
func _Cgo___GoBytes(unsafe.Pointer, uintptr) []byte
func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte {
return C.__GoBytes(ptr, uintptr(length))
func _Cgo_GoBytes(ptr unsafe.Pointer, length _Cgo_int) []byte {
return _Cgo___GoBytes(ptr, uintptr(length))
}
//go:linkname C.__CBytes runtime.cgo_CBytes
func C.__CBytes([]byte) unsafe.Pointer
//go:linkname _Cgo___CBytes runtime.cgo_CBytes
func _Cgo___CBytes([]byte) unsafe.Pointer
func C.CBytes(b []byte) unsafe.Pointer {
return C.__CBytes(b)
func _Cgo_CBytes(b []byte) unsafe.Pointer {
return _Cgo___CBytes(b)
}
//go:linkname C.__get_errno_num runtime.cgo_errno
func C.__get_errno_num() uintptr
//go:linkname _Cgo___get_errno_num runtime.cgo_errno
func _Cgo___get_errno_num() uintptr
func C.__get_errno() error {
return syscall.Errno(C.__get_errno_num())
func _Cgo___get_errno() error {
return syscall.Errno(_Cgo___get_errno_num())
}
type (
C.char uint8
C.schar int8
C.uchar uint8
C.short int16
C.ushort uint16
C.int int32
C.uint uint32
C.long int32
C.ulong uint32
C.longlong int64
C.ulonglong uint64
_Cgo_char uint8
_Cgo_schar int8
_Cgo_uchar uint8
_Cgo_short int16
_Cgo_ushort uint16
_Cgo_int int32
_Cgo_uint uint32
_Cgo_long int32
_Cgo_ulong uint32
_Cgo_longlong int64
_Cgo_ulonglong uint64
)
type C.struct_point_t struct {
x C.int
y C.int
type _Cgo_struct_point_t struct {
x _Cgo_int
y _Cgo_int
}
type C.point_t = C.struct_point_t
type _Cgo_point_t = _Cgo_struct_point_t
const C.SOME_CONST_3 = 1234
const C.SOME_PARAM_CONST_valid = 3 + 4
const _Cgo_SOME_CONST_3 = 1234
const _Cgo_SOME_PARAM_CONST_valid = 3 + 4
+33 -33
View File
@@ -10,53 +10,53 @@ import "unsafe"
var _ unsafe.Pointer
//go:linkname C.CString runtime.cgo_CString
func C.CString(string) *C.char
//go:linkname _Cgo_CString runtime.cgo_CString
func _Cgo_CString(string) *_Cgo_char
//go:linkname C.GoString runtime.cgo_GoString
func C.GoString(*C.char) string
//go:linkname _Cgo_GoString runtime.cgo_GoString
func _Cgo_GoString(*_Cgo_char) string
//go:linkname C.__GoStringN runtime.cgo_GoStringN
func C.__GoStringN(*C.char, uintptr) string
//go:linkname _Cgo___GoStringN runtime.cgo_GoStringN
func _Cgo___GoStringN(*_Cgo_char, uintptr) string
func C.GoStringN(cstr *C.char, length C.int) string {
return C.__GoStringN(cstr, uintptr(length))
func _Cgo_GoStringN(cstr *_Cgo_char, length _Cgo_int) string {
return _Cgo___GoStringN(cstr, uintptr(length))
}
//go:linkname C.__GoBytes runtime.cgo_GoBytes
func C.__GoBytes(unsafe.Pointer, uintptr) []byte
//go:linkname _Cgo___GoBytes runtime.cgo_GoBytes
func _Cgo___GoBytes(unsafe.Pointer, uintptr) []byte
func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte {
return C.__GoBytes(ptr, uintptr(length))
func _Cgo_GoBytes(ptr unsafe.Pointer, length _Cgo_int) []byte {
return _Cgo___GoBytes(ptr, uintptr(length))
}
//go:linkname C.__CBytes runtime.cgo_CBytes
func C.__CBytes([]byte) unsafe.Pointer
//go:linkname _Cgo___CBytes runtime.cgo_CBytes
func _Cgo___CBytes([]byte) unsafe.Pointer
func C.CBytes(b []byte) unsafe.Pointer {
return C.__CBytes(b)
func _Cgo_CBytes(b []byte) unsafe.Pointer {
return _Cgo___CBytes(b)
}
//go:linkname C.__get_errno_num runtime.cgo_errno
func C.__get_errno_num() uintptr
//go:linkname _Cgo___get_errno_num runtime.cgo_errno
func _Cgo___get_errno_num() uintptr
func C.__get_errno() error {
return syscall.Errno(C.__get_errno_num())
func _Cgo___get_errno() error {
return syscall.Errno(_Cgo___get_errno_num())
}
type (
C.char uint8
C.schar int8
C.uchar uint8
C.short int16
C.ushort uint16
C.int int32
C.uint uint32
C.long int32
C.ulong uint32
C.longlong int64
C.ulonglong uint64
_Cgo_char uint8
_Cgo_schar int8
_Cgo_uchar uint8
_Cgo_short int16
_Cgo_ushort uint16
_Cgo_int int32
_Cgo_uint uint32
_Cgo_long int32
_Cgo_ulong uint32
_Cgo_longlong int64
_Cgo_ulonglong uint64
)
const C.BAR = 3
const C.FOO_H = 1
const _Cgo_BAR = 3
const _Cgo_FOO_H = 1
+42 -42
View File
@@ -5,80 +5,80 @@ import "unsafe"
var _ unsafe.Pointer
//go:linkname C.CString runtime.cgo_CString
func C.CString(string) *C.char
//go:linkname _Cgo_CString runtime.cgo_CString
func _Cgo_CString(string) *_Cgo_char
//go:linkname C.GoString runtime.cgo_GoString
func C.GoString(*C.char) string
//go:linkname _Cgo_GoString runtime.cgo_GoString
func _Cgo_GoString(*_Cgo_char) string
//go:linkname C.__GoStringN runtime.cgo_GoStringN
func C.__GoStringN(*C.char, uintptr) string
//go:linkname _Cgo___GoStringN runtime.cgo_GoStringN
func _Cgo___GoStringN(*_Cgo_char, uintptr) string
func C.GoStringN(cstr *C.char, length C.int) string {
return C.__GoStringN(cstr, uintptr(length))
func _Cgo_GoStringN(cstr *_Cgo_char, length _Cgo_int) string {
return _Cgo___GoStringN(cstr, uintptr(length))
}
//go:linkname C.__GoBytes runtime.cgo_GoBytes
func C.__GoBytes(unsafe.Pointer, uintptr) []byte
//go:linkname _Cgo___GoBytes runtime.cgo_GoBytes
func _Cgo___GoBytes(unsafe.Pointer, uintptr) []byte
func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte {
return C.__GoBytes(ptr, uintptr(length))
func _Cgo_GoBytes(ptr unsafe.Pointer, length _Cgo_int) []byte {
return _Cgo___GoBytes(ptr, uintptr(length))
}
//go:linkname C.__CBytes runtime.cgo_CBytes
func C.__CBytes([]byte) unsafe.Pointer
//go:linkname _Cgo___CBytes runtime.cgo_CBytes
func _Cgo___CBytes([]byte) unsafe.Pointer
func C.CBytes(b []byte) unsafe.Pointer {
return C.__CBytes(b)
func _Cgo_CBytes(b []byte) unsafe.Pointer {
return _Cgo___CBytes(b)
}
//go:linkname C.__get_errno_num runtime.cgo_errno
func C.__get_errno_num() uintptr
//go:linkname _Cgo___get_errno_num runtime.cgo_errno
func _Cgo___get_errno_num() uintptr
func C.__get_errno() error {
return syscall.Errno(C.__get_errno_num())
func _Cgo___get_errno() error {
return syscall.Errno(_Cgo___get_errno_num())
}
type (
C.char uint8
C.schar int8
C.uchar uint8
C.short int16
C.ushort uint16
C.int int32
C.uint uint32
C.long int32
C.ulong uint32
C.longlong int64
C.ulonglong uint64
_Cgo_char uint8
_Cgo_schar int8
_Cgo_uchar uint8
_Cgo_short int16
_Cgo_ushort uint16
_Cgo_int int32
_Cgo_uint uint32
_Cgo_long int32
_Cgo_ulong uint32
_Cgo_longlong int64
_Cgo_ulonglong uint64
)
//export foo
func C.foo(a C.int, b C.int) C.int
func _Cgo_foo(a _Cgo_int, b _Cgo_int) _Cgo_int
var C.foo$funcaddr unsafe.Pointer
var _Cgo_foo$funcaddr unsafe.Pointer
//export variadic0
//go:variadic
func C.variadic0()
func _Cgo_variadic0()
var C.variadic0$funcaddr unsafe.Pointer
var _Cgo_variadic0$funcaddr unsafe.Pointer
//export variadic2
//go:variadic
func C.variadic2(x C.int, y C.int)
func _Cgo_variadic2(x _Cgo_int, y _Cgo_int)
var C.variadic2$funcaddr unsafe.Pointer
var _Cgo_variadic2$funcaddr unsafe.Pointer
//export _Cgo_static_173c95a79b6df1980521_staticfunc
func C.staticfunc!symbols.go(x C.int)
func _Cgo_staticfunc!symbols.go(x _Cgo_int)
var C.staticfunc!symbols.go$funcaddr unsafe.Pointer
var _Cgo_staticfunc!symbols.go$funcaddr unsafe.Pointer
//export notEscapingFunction
//go:noescape
func C.notEscapingFunction(a *C.int)
func _Cgo_notEscapingFunction(a *_Cgo_int)
var C.notEscapingFunction$funcaddr unsafe.Pointer
var _Cgo_notEscapingFunction$funcaddr unsafe.Pointer
//go:extern someValue
var C.someValue C.int
var _Cgo_someValue _Cgo_int
+103 -99
View File
@@ -5,158 +5,162 @@ import "unsafe"
var _ unsafe.Pointer
//go:linkname C.CString runtime.cgo_CString
func C.CString(string) *C.char
//go:linkname _Cgo_CString runtime.cgo_CString
func _Cgo_CString(string) *_Cgo_char
//go:linkname C.GoString runtime.cgo_GoString
func C.GoString(*C.char) string
//go:linkname _Cgo_GoString runtime.cgo_GoString
func _Cgo_GoString(*_Cgo_char) string
//go:linkname C.__GoStringN runtime.cgo_GoStringN
func C.__GoStringN(*C.char, uintptr) string
//go:linkname _Cgo___GoStringN runtime.cgo_GoStringN
func _Cgo___GoStringN(*_Cgo_char, uintptr) string
func C.GoStringN(cstr *C.char, length C.int) string {
return C.__GoStringN(cstr, uintptr(length))
func _Cgo_GoStringN(cstr *_Cgo_char, length _Cgo_int) string {
return _Cgo___GoStringN(cstr, uintptr(length))
}
//go:linkname C.__GoBytes runtime.cgo_GoBytes
func C.__GoBytes(unsafe.Pointer, uintptr) []byte
//go:linkname _Cgo___GoBytes runtime.cgo_GoBytes
func _Cgo___GoBytes(unsafe.Pointer, uintptr) []byte
func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte {
return C.__GoBytes(ptr, uintptr(length))
func _Cgo_GoBytes(ptr unsafe.Pointer, length _Cgo_int) []byte {
return _Cgo___GoBytes(ptr, uintptr(length))
}
//go:linkname C.__CBytes runtime.cgo_CBytes
func C.__CBytes([]byte) unsafe.Pointer
//go:linkname _Cgo___CBytes runtime.cgo_CBytes
func _Cgo___CBytes([]byte) unsafe.Pointer
func C.CBytes(b []byte) unsafe.Pointer {
return C.__CBytes(b)
func _Cgo_CBytes(b []byte) unsafe.Pointer {
return _Cgo___CBytes(b)
}
//go:linkname C.__get_errno_num runtime.cgo_errno
func C.__get_errno_num() uintptr
//go:linkname _Cgo___get_errno_num runtime.cgo_errno
func _Cgo___get_errno_num() uintptr
func C.__get_errno() error {
return syscall.Errno(C.__get_errno_num())
func _Cgo___get_errno() error {
return syscall.Errno(_Cgo___get_errno_num())
}
type (
C.char uint8
C.schar int8
C.uchar uint8
C.short int16
C.ushort uint16
C.int int32
C.uint uint32
C.long int32
C.ulong uint32
C.longlong int64
C.ulonglong uint64
_Cgo_char uint8
_Cgo_schar int8
_Cgo_uchar uint8
_Cgo_short int16
_Cgo_ushort uint16
_Cgo_int int32
_Cgo_uint uint32
_Cgo_long int32
_Cgo_ulong uint32
_Cgo_longlong int64
_Cgo_ulonglong uint64
)
type C.myint = C.int
type C.struct_point2d_t struct {
x C.int
y C.int
type _Cgo_myint = _Cgo_int
type _Cgo_struct_point2d_t struct {
x _Cgo_int
y _Cgo_int
}
type C.point2d_t = C.struct_point2d_t
type C.struct_point3d struct {
x C.int
y C.int
z C.int
type _Cgo_point2d_t = _Cgo_struct_point2d_t
type _Cgo_struct_point3d struct {
x _Cgo_int
y _Cgo_int
z _Cgo_int
}
type C.point3d_t = C.struct_point3d
type C.struct_type1 struct {
_type C.int
__type C.int
___type C.int
type _Cgo_point3d_t = _Cgo_struct_point3d
type _Cgo_struct_type1 struct {
_type _Cgo_int
__type _Cgo_int
___type _Cgo_int
}
type C.struct_type2 struct{ _type C.int }
type C.union_union1_t struct{ i C.int }
type C.union1_t = C.union_union1_t
type C.union_union3_t struct{ $union uint64 }
type _Cgo_struct_type2 struct{ _type _Cgo_int }
type _Cgo_union_union1_t struct{ i _Cgo_int }
type _Cgo_union1_t = _Cgo_union_union1_t
type _Cgo_union_union3_t struct{ $union uint64 }
func (union *C.union_union3_t) unionfield_i() *C.int { return (*C.int)(unsafe.Pointer(&union.$union)) }
func (union *C.union_union3_t) unionfield_d() *float64 {
func (union *_Cgo_union_union3_t) unionfield_i() *_Cgo_int {
return (*_Cgo_int)(unsafe.Pointer(&union.$union))
}
func (union *_Cgo_union_union3_t) unionfield_d() *float64 {
return (*float64)(unsafe.Pointer(&union.$union))
}
func (union *C.union_union3_t) unionfield_s() *C.short {
return (*C.short)(unsafe.Pointer(&union.$union))
func (union *_Cgo_union_union3_t) unionfield_s() *_Cgo_short {
return (*_Cgo_short)(unsafe.Pointer(&union.$union))
}
type C.union3_t = C.union_union3_t
type C.union_union2d struct{ $union [2]uint64 }
type _Cgo_union3_t = _Cgo_union_union3_t
type _Cgo_union_union2d struct{ $union [2]uint64 }
func (union *C.union_union2d) unionfield_i() *C.int { return (*C.int)(unsafe.Pointer(&union.$union)) }
func (union *C.union_union2d) unionfield_d() *[2]float64 {
func (union *_Cgo_union_union2d) unionfield_i() *_Cgo_int {
return (*_Cgo_int)(unsafe.Pointer(&union.$union))
}
func (union *_Cgo_union_union2d) unionfield_d() *[2]float64 {
return (*[2]float64)(unsafe.Pointer(&union.$union))
}
type C.union2d_t = C.union_union2d
type C.union_unionarray_t struct{ arr [10]C.uchar }
type C.unionarray_t = C.union_unionarray_t
type C._Ctype_union___0 struct{ $union [3]uint32 }
type _Cgo_union2d_t = _Cgo_union_union2d
type _Cgo_union_unionarray_t struct{ arr [10]_Cgo_uchar }
type _Cgo_unionarray_t = _Cgo_union_unionarray_t
type _Cgo__Ctype_union___0 struct{ $union [3]uint32 }
func (union *C._Ctype_union___0) unionfield_area() *C.point2d_t {
return (*C.point2d_t)(unsafe.Pointer(&union.$union))
func (union *_Cgo__Ctype_union___0) unionfield_area() *_Cgo_point2d_t {
return (*_Cgo_point2d_t)(unsafe.Pointer(&union.$union))
}
func (union *C._Ctype_union___0) unionfield_solid() *C.point3d_t {
return (*C.point3d_t)(unsafe.Pointer(&union.$union))
func (union *_Cgo__Ctype_union___0) unionfield_solid() *_Cgo_point3d_t {
return (*_Cgo_point3d_t)(unsafe.Pointer(&union.$union))
}
type C.struct_struct_nested_t struct {
begin C.point2d_t
end C.point2d_t
tag C.int
type _Cgo_struct_struct_nested_t struct {
begin _Cgo_point2d_t
end _Cgo_point2d_t
tag _Cgo_int
coord C._Ctype_union___0
coord _Cgo__Ctype_union___0
}
type C.struct_nested_t = C.struct_struct_nested_t
type C.union_union_nested_t struct{ $union [2]uint64 }
type _Cgo_struct_nested_t = _Cgo_struct_struct_nested_t
type _Cgo_union_union_nested_t struct{ $union [2]uint64 }
func (union *C.union_union_nested_t) unionfield_point() *C.point3d_t {
return (*C.point3d_t)(unsafe.Pointer(&union.$union))
func (union *_Cgo_union_union_nested_t) unionfield_point() *_Cgo_point3d_t {
return (*_Cgo_point3d_t)(unsafe.Pointer(&union.$union))
}
func (union *C.union_union_nested_t) unionfield_array() *C.unionarray_t {
return (*C.unionarray_t)(unsafe.Pointer(&union.$union))
func (union *_Cgo_union_union_nested_t) unionfield_array() *_Cgo_unionarray_t {
return (*_Cgo_unionarray_t)(unsafe.Pointer(&union.$union))
}
func (union *C.union_union_nested_t) unionfield_thing() *C.union3_t {
return (*C.union3_t)(unsafe.Pointer(&union.$union))
func (union *_Cgo_union_union_nested_t) unionfield_thing() *_Cgo_union3_t {
return (*_Cgo_union3_t)(unsafe.Pointer(&union.$union))
}
type C.union_nested_t = C.union_union_nested_t
type C.enum_option = C.int
type C.option_t = C.enum_option
type C.enum_option2_t = C.uint
type C.option2_t = C.enum_option2_t
type C.struct_types_t struct {
type _Cgo_union_nested_t = _Cgo_union_union_nested_t
type _Cgo_enum_option = _Cgo_int
type _Cgo_option_t = _Cgo_enum_option
type _Cgo_enum_option2_t = _Cgo_uint
type _Cgo_option2_t = _Cgo_enum_option2_t
type _Cgo_struct_types_t struct {
f float32
d float64
ptr *C.int
ptr *_Cgo_int
}
type C.types_t = C.struct_types_t
type C.myIntArray = [10]C.int
type C.struct_bitfield_t struct {
start C.uchar
__bitfield_1 C.uchar
type _Cgo_types_t = _Cgo_struct_types_t
type _Cgo_myIntArray = [10]_Cgo_int
type _Cgo_struct_bitfield_t struct {
start _Cgo_uchar
__bitfield_1 _Cgo_uchar
d C.uchar
e C.uchar
d _Cgo_uchar
e _Cgo_uchar
}
func (s *C.struct_bitfield_t) bitfield_a() C.uchar { return s.__bitfield_1 & 0x1f }
func (s *C.struct_bitfield_t) set_bitfield_a(value C.uchar) {
func (s *_Cgo_struct_bitfield_t) bitfield_a() _Cgo_uchar { return s.__bitfield_1 & 0x1f }
func (s *_Cgo_struct_bitfield_t) set_bitfield_a(value _Cgo_uchar) {
s.__bitfield_1 = s.__bitfield_1&^0x1f | value&0x1f<<0
}
func (s *C.struct_bitfield_t) bitfield_b() C.uchar {
func (s *_Cgo_struct_bitfield_t) bitfield_b() _Cgo_uchar {
return s.__bitfield_1 >> 5 & 0x1
}
func (s *C.struct_bitfield_t) set_bitfield_b(value C.uchar) {
func (s *_Cgo_struct_bitfield_t) set_bitfield_b(value _Cgo_uchar) {
s.__bitfield_1 = s.__bitfield_1&^0x20 | value&0x1<<5
}
func (s *C.struct_bitfield_t) bitfield_c() C.uchar {
func (s *_Cgo_struct_bitfield_t) bitfield_c() _Cgo_uchar {
return s.__bitfield_1 >> 6
}
func (s *C.struct_bitfield_t) set_bitfield_c(value C.uchar,
func (s *_Cgo_struct_bitfield_t) set_bitfield_c(value _Cgo_uchar,
) { s.__bitfield_1 = s.__bitfield_1&0x3f | value<<6 }
type C.bitfield_t = C.struct_bitfield_t
type _Cgo_bitfield_t = _Cgo_struct_bitfield_t
+1 -1
View File
@@ -8,7 +8,7 @@ import (
)
var (
validBuildModeOptions = []string{"default", "c-shared"}
validBuildModeOptions = []string{"default", "c-shared", "wasi-legacy"}
validGCOptions = []string{"none", "leaking", "conservative", "custom", "precise"}
validSchedulerOptions = []string{"none", "tasks", "asyncify"}
validSerialOptions = []string{"none", "uart", "usb", "rtt"}
+3 -28
View File
@@ -356,17 +356,7 @@ func defaultTarget(options *Options) (*TargetSpec, error) {
return nil, fmt.Errorf("invalid GOMIPS=%s: must be hardfloat or softfloat", options.GOMIPS)
}
case "wasm":
llvmarch = "wasm32"
spec.CPU = "generic"
spec.Features = "+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types"
spec.BuildTags = append(spec.BuildTags, "tinygo.wasm")
spec.CFlags = append(spec.CFlags,
"-mbulk-memory",
"-mnontrapping-fptoint",
"-mno-multivalue",
"-mno-reference-types",
"-msign-ext",
)
return nil, fmt.Errorf("GOARCH=wasm but GOOS is unset. Please set GOOS to wasm, wasip1, or wasip2.")
default:
return nil, fmt.Errorf("unknown GOARCH=%s", options.GOARCH)
}
@@ -446,23 +436,8 @@ func defaultTarget(options *Options) (*TargetSpec, error) {
"--no-insert-timestamp",
"--no-dynamicbase",
)
case "wasip1":
spec.GC = "" // use default GC
spec.Scheduler = "asyncify"
spec.Linker = "wasm-ld"
spec.RTLib = "compiler-rt"
spec.Libc = "wasi-libc"
spec.DefaultStackSize = 1024 * 64 // 64kB
spec.LDFlags = append(spec.LDFlags,
"--stack-first",
"--no-demangle",
)
spec.Emulator = "wasmtime run --dir={tmpDir}::/tmp {}"
spec.ExtraFiles = append(spec.ExtraFiles,
"src/runtime/asm_tinygowasm.S",
"src/internal/task/task_asyncify_wasm.S",
)
llvmos = "wasi"
case "wasm", "wasip1", "wasip2":
return nil, fmt.Errorf("GOOS=%s but GOARCH is unset. Please set GOARCH to wasm", options.GOOS)
default:
return nil, fmt.Errorf("unknown GOOS=%s", options.GOOS)
}
+6 -5
View File
@@ -18,11 +18,12 @@ var stdlibAliases = map[string]string{
// crypto packages
"crypto/ed25519/internal/edwards25519/field.feMul": "crypto/ed25519/internal/edwards25519/field.feMulGeneric",
"crypto/internal/edwards25519/field.feSquare": "crypto/ed25519/internal/edwards25519/field.feSquareGeneric",
"crypto/md5.block": "crypto/md5.blockGeneric",
"crypto/sha1.block": "crypto/sha1.blockGeneric",
"crypto/sha1.blockAMD64": "crypto/sha1.blockGeneric",
"crypto/sha256.block": "crypto/sha256.blockGeneric",
"crypto/sha512.blockAMD64": "crypto/sha512.blockGeneric",
"crypto/md5.block": "crypto/md5.blockGeneric",
"crypto/sha1.block": "crypto/sha1.blockGeneric",
"crypto/sha1.blockAMD64": "crypto/sha1.blockGeneric",
"crypto/sha256.block": "crypto/sha256.blockGeneric",
"crypto/sha512.blockAMD64": "crypto/sha512.blockGeneric",
"internal/chacha8rand.block": "internal/chacha8rand.block_generic",
// AES
"crypto/aes.decryptBlockAsm": "crypto/aes.decryptBlock",
+8 -4
View File
@@ -283,6 +283,11 @@ func (c *compilerContext) getFunctionInfo(f *ssa.Function) functionInfo {
info.wasmName = "_start"
info.exported = true
}
if info.linkName == "runtime.wasmEntryLegacy" && c.BuildMode == "wasi-legacy" {
info.linkName = "_start"
info.wasmName = "_start"
info.exported = true
}
// Check for //go: pragmas, which may change the link name (among others).
c.parsePragmas(&info, f)
@@ -427,9 +432,8 @@ func (c *compilerContext) parsePragmas(info *functionInfo, f *ssa.Function) {
// pass for C variadic functions. This includes both explicit
// (with ...) and implicit (no parameters in signature)
// functions.
if strings.HasPrefix(f.Name(), "C.") {
// This prefix cannot naturally be created, it must have
// been created as a result of CGo preprocessing.
if strings.HasPrefix(f.Name(), "_Cgo_") {
// This prefix was created as a result of CGo preprocessing.
info.variadic = true
}
}
@@ -442,7 +446,7 @@ func (c *compilerContext) parsePragmas(info *functionInfo, f *ssa.Function) {
// The list of allowed types is based on this proposal:
// https://github.com/golang/go/issues/59149
func (c *compilerContext) checkWasmImportExport(f *ssa.Function, pragma string) {
if c.pkg.Path() == "runtime" || c.pkg.Path() == "syscall/js" || c.pkg.Path() == "syscall" {
if c.pkg.Path() == "runtime" || c.pkg.Path() == "syscall/js" || c.pkg.Path() == "syscall" || c.pkg.Path() == "crypto/internal/sysrand" {
// The runtime is a special case. Allow all kinds of parameters
// (importantly, including pointers).
return
+1 -1
View File
@@ -10,7 +10,7 @@ import (
// Version of TinyGo.
// Update this value before release of new version of software.
const version = "0.36.0-dev"
const version = "0.36.0"
// Return TinyGo version, either in the form 0.30.0 or as a development version
// (like 0.30.0-dev-abcd012).
+3 -3
View File
@@ -970,9 +970,9 @@ func (r *runner) runAtRuntime(fn *function, inst instruction, locals []value, me
case llvm.Call:
llvmFn := operands[len(operands)-1]
args := operands[:len(operands)-1]
for _, arg := range args {
if arg.Type().TypeKind() == llvm.PointerTypeKind {
err := mem.markExternalStore(arg)
for _, op := range operands {
if op.Type().TypeKind() == llvm.PointerTypeKind {
err := mem.markExternalStore(op)
if err != nil {
return r.errorAt(inst, err)
}
+2
View File
@@ -269,6 +269,8 @@ func pathsToOverride(goMinor int, needsSyscallPackage bool) map[string]bool {
if needsSyscallPackage {
paths["syscall/"] = true // include syscall/js
paths["internal/syscall/"] = true
paths["internal/syscall/unix/"] = false
}
return paths
}
+19 -3
View File
@@ -1501,7 +1501,7 @@ func main() {
var tags buildutil.TagsFlag
flag.Var(&tags, "tags", "a space-separated list of extra build tags")
target := flag.String("target", "", "chip/board name or JSON target specification file")
buildMode := flag.String("buildmode", "", "build mode to use (default, c-shared)")
buildMode := flag.String("buildmode", "", "build mode to use (default, c-shared, wasi-legacy)")
var stackSize uint64
flag.Func("stack-size", "goroutine stack size (if unknown at compile time)", func(s string) error {
size, err := bytesize.Parse(s)
@@ -1684,8 +1684,24 @@ func main() {
usage(command)
os.Exit(1)
}
if options.Target == "" && filepath.Ext(outpath) == ".wasm" {
options.Target = "wasm"
if options.Target == "" {
switch {
case options.GOARCH == "wasm":
switch options.GOOS {
case "js":
options.Target = "wasm"
case "wasip1":
options.Target = "wasip1"
case "wasip2":
options.Target = "wasip2"
default:
fmt.Fprintln(os.Stderr, "GOARCH=wasm but GOOS is not set correctly. Please set GOOS to wasm, wasip1, or wasip2.")
os.Exit(1)
}
case filepath.Ext(outpath) == ".wasm":
fmt.Fprintln(os.Stderr, "you appear to want to build a wasm file, but have not specified either a target flag, or the GOARCH/GOOS to use.")
os.Exit(1)
}
}
err := Build(pkgName, outpath, options)
+9
View File
@@ -594,6 +594,15 @@ func TestWasmExport(t *testing.T) {
noOutput: true, // wasm-unknown cannot produce output
command: true,
},
// Test buildmode=wasi-legacy with WASI.
{
name: "WASIp1-legacy",
target: "wasip1",
buildMode: "wasi-legacy",
scheduler: "none",
file: "wasmexport-noscheduler.go",
command: true,
},
}
for _, tc := range tests {
+1 -1
View File
@@ -1,4 +1,4 @@
//go:build nrf || (stm32 && !(stm32f103 || stm32l0x1)) || (sam && atsamd51) || (sam && atsame5x) || esp32c3 || tkey
//go:build nrf || (stm32 && !(stm32f103 || stm32l0x1)) || (sam && atsamd51) || (sam && atsame5x) || esp32c3 || tkey || (tinygo.riscv32 && virt)
// If you update the above build constraint, you'll probably also need to update
// src/runtime/rand_hwrng.go.
+31
View File
@@ -17,6 +17,37 @@ import (
"time"
)
const (
VersionTLS10 = 0x0301
VersionTLS11 = 0x0302
VersionTLS12 = 0x0303
VersionTLS13 = 0x0304
// Deprecated: SSLv3 is cryptographically broken, and is no longer
// supported by this package. See golang.org/issue/32716.
VersionSSL30 = 0x0300
)
// VersionName returns the name for the provided TLS version number
// (e.g. "TLS 1.3"), or a fallback representation of the value if the
// version is not implemented by this package.
func VersionName(version uint16) string {
switch version {
case VersionSSL30:
return "SSLv3"
case VersionTLS10:
return "TLS 1.0"
case VersionTLS11:
return "TLS 1.1"
case VersionTLS12:
return "TLS 1.2"
case VersionTLS13:
return "TLS 1.3"
default:
return fmt.Sprintf("0x%04X", version)
}
}
// CurveID is the type of a TLS identifier for an elliptic curve. See
// https://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-8.
//
+7
View File
@@ -0,0 +1,7 @@
package abi
type Type struct {
// Intentionally left empty. TinyGo uses a different way to represent types,
// so this is unimplementable. The type definition here is purely for
// compatibility.
}
+7
View File
@@ -0,0 +1,7 @@
package unix
const (
R_OK = 0x4
W_OK = 0x2
X_OK = 0x1
)
+10
View File
@@ -0,0 +1,10 @@
package unix
import "syscall"
func Eaccess(path string, mode uint32) error {
// We don't support this syscall on baremetal or wasm.
// Callers are generally able to deal with this since unix.Eaccess also
// isn't available on Android.
return syscall.ENOSYS
}
+12
View File
@@ -0,0 +1,12 @@
package unix
type GetRandomFlag uintptr
const (
GRND_NONBLOCK GetRandomFlag = 0x0001
GRND_RANDOM GetRandomFlag = 0x0002
)
func GetRandom(p []byte, flags GetRandomFlag) (n int, err error) {
panic("todo: unix.GetRandom")
}
+3
View File
@@ -21,6 +21,9 @@ type Task struct {
// state is the underlying running state of the task.
state state
// This is needed for some crypto packages.
FipsIndicator uint8
// DeferFrame stores a pointer to the (stack allocated) defer frame of the
// goroutine that is used for the recover builtin.
DeferFrame unsafe.Pointer
+77
View File
@@ -0,0 +1,77 @@
//go:build hw_651
package machine
// No-name brand board based on the nRF51822 chip with low frequency crystal on board.
// Pinout (reverse engineered from the board) can be found here:
// https://aviatorahmet.blogspot.com/2020/12/pinout-of-nrf51822-board.html
// https://cr0wg4n.medium.com/pinout-nrf51822-board-hw-651-78da2eda8894
const HasLowFrequencyCrystal = true
var DefaultUART = UART0
// GPIO pins on header J1
const (
J1_01 = P0_21
J1_03 = P0_23
J1_04 = P0_22
J1_05 = P0_25
J1_06 = P0_24
J1_09 = P0_29
J1_10 = P0_28
J1_11 = P0_30
J1_13 = P0_00
J1_15 = P0_02
J1_17 = P0_04
J1_16 = P0_01
J1_18 = P0_03
)
// GPIO pins on header J2
const (
J2_01 = P0_20
J2_03 = P0_18
J2_04 = P0_19
J2_07 = P0_16
J2_08 = P0_15
J2_09 = P0_14
J2_10 = P0_13
J2_11 = P0_12
J2_12 = P0_11
J2_13 = P0_10
J2_14 = P0_09
J2_15 = P0_08
J2_16 = P0_07
J2_17 = P0_06
J2_18 = P0_05
)
// UART pins
const (
UART_TX_PIN = P0_24 // J1_06 on the board
UART_RX_PIN = P0_25 // J1_05 on the board
)
// ADC pins
const (
ADC0 = P0_03 // J1_18 on the board
ADC1 = P0_02 // J1_15 on the board
ADC2 = P0_01 // J1_16 on the board
ADC3 = P0_04 // J1_17 on the board
ADC4 = P0_05 // J2_18 on the board
ADC5 = P0_06 // J2_17 on the board
)
// I2C pins
const (
SDA_PIN = P0_30 // J1_11 on the board
SCL_PIN = P0_00 // J1_13 on the board
)
// SPI pins
const (
SPI0_SCK_PIN = P0_23 // J1_03 on the board
SPI0_SDO_PIN = P0_21 // J1_01 on the board
SPI0_SDI_PIN = P0_22 // J1_04 on the board
)
+98
View File
@@ -0,0 +1,98 @@
//go:build pga2350
package machine
// PGA2350 pin definitions.
const (
GP0 = GPIO0
GP1 = GPIO1
GP2 = GPIO2
GP3 = GPIO3
GP4 = GPIO4
GP5 = GPIO5
GP6 = GPIO6
GP7 = GPIO7
GP8 = GPIO8
GP9 = GPIO9
GP10 = GPIO10
GP11 = GPIO11
GP12 = GPIO12
GP13 = GPIO13
GP14 = GPIO14
GP15 = GPIO15
GP16 = GPIO16
GP17 = GPIO17
GP18 = GPIO18
GP19 = GPIO19
GP20 = GPIO20
GP21 = GPIO21
GP22 = GPIO22
GP26 = GPIO26
GP27 = GPIO27
GP28 = GPIO28
GP29 = GPIO29
GP30 = GPIO30 // peripherals: PWM7 channel A
GP31 = GPIO31 // peripherals: PWM7 channel B
GP32 = GPIO32 // peripherals: PWM8 channel A
GP33 = GPIO33 // peripherals: PWM8 channel B
GP34 = GPIO34 // peripherals: PWM9 channel A
GP35 = GPIO35 // peripherals: PWM9 channel B
GP36 = GPIO36 // peripherals: PWM10 channel A
GP37 = GPIO37 // peripherals: PWM10 channel B
GP38 = GPIO38 // peripherals: PWM11 channel A
GP39 = GPIO39 // peripherals: PWM11 channel B
GP40 = GPIO40 // peripherals: PWM8 channel A
GP41 = GPIO41 // peripherals: PWM8 channel B
GP42 = GPIO42 // peripherals: PWM9 channel A
GP43 = GPIO43 // peripherals: PWM9 channel B
GP44 = GPIO44 // peripherals: PWM10 channel A
GP45 = GPIO45 // peripherals: PWM10 channel B
GP46 = GPIO46 // peripherals: PWM11 channel A
GP47 = GPIO47 // peripherals: PWM11 channel B
)
var DefaultUART = UART0
// Peripheral defaults.
const (
xoscFreq = 12 // MHz
I2C0_SDA_PIN = GP4
I2C0_SCL_PIN = GP5
I2C1_SDA_PIN = GP2
I2C1_SCL_PIN = GP3
// Default Serial Clock Bus 0 for SPI communications
SPI0_SCK_PIN = GPIO18
// Default Serial Out Bus 0 for SPI communications
SPI0_SDO_PIN = GPIO19 // Tx
// Default Serial In Bus 0 for SPI communications
SPI0_SDI_PIN = GPIO16 // Rx
// Default Serial Clock Bus 1 for SPI communications
SPI1_SCK_PIN = GPIO10
// Default Serial Out Bus 1 for SPI communications
SPI1_SDO_PIN = GPIO11 // Tx
// Default Serial In Bus 1 for SPI communications
SPI1_SDI_PIN = GPIO12 // Rx
UART0_TX_PIN = GPIO0
UART0_RX_PIN = GPIO1
UART1_TX_PIN = GPIO8
UART1_RX_PIN = GPIO9
UART_TX_PIN = UART0_TX_PIN
UART_RX_PIN = UART0_RX_PIN
)
// USB identifiers
const (
usb_STRING_PRODUCT = "PGA2350"
usb_STRING_MANUFACTURER = "Pimoroni"
)
var (
usb_VID uint16 = 0x2E8A
usb_PID uint16 = 0x000A
)
+93
View File
@@ -0,0 +1,93 @@
//go:build pico_plus2
package machine
// GPIO pins
const (
GP0 Pin = GPIO0
GP1 Pin = GPIO1
GP2 Pin = GPIO2
GP3 Pin = GPIO3
GP4 Pin = GPIO4
GP5 Pin = GPIO5
GP6 Pin = GPIO6
GP7 Pin = GPIO7
GP8 Pin = GPIO8
GP9 Pin = GPIO9
GP10 Pin = GPIO10
GP11 Pin = GPIO11
GP12 Pin = GPIO12
GP13 Pin = GPIO13
GP14 Pin = GPIO14
GP15 Pin = GPIO15
GP16 Pin = GPIO16
GP17 Pin = GPIO17
GP18 Pin = GPIO18
GP19 Pin = GPIO19
GP20 Pin = GPIO20
GP21 Pin = GPIO21
GP22 Pin = GPIO22
GP26 Pin = GPIO26
GP27 Pin = GPIO27
GP28 Pin = GPIO28
GP32 Pin = GPIO32
GP33 Pin = GPIO33
GP34 Pin = GPIO34
GP35 Pin = GPIO35
GP36 Pin = GPIO36
// Onboard LED
LED Pin = GPIO25
// Onboard crystal oscillator frequency, in MHz.
xoscFreq = 12 // MHz
)
// I2C Default pins on Raspberry Pico.
const (
I2C0_SDA_PIN = GP4
I2C0_SCL_PIN = GP5
I2C1_SDA_PIN = GP2
I2C1_SCL_PIN = GP3
)
// SPI default pins
const (
// Default Serial Clock Bus 0 for SPI communications
SPI0_SCK_PIN = GPIO18
// Default Serial Out Bus 0 for SPI communications
SPI0_SDO_PIN = GPIO19 // Tx
// Default Serial In Bus 0 for SPI communications
SPI0_SDI_PIN = GPIO16 // Rx
// Default Serial Clock Bus 1 for SPI communications
SPI1_SCK_PIN = GPIO10
// Default Serial Out Bus 1 for SPI communications
SPI1_SDO_PIN = GPIO11 // Tx
// Default Serial In Bus 1 for SPI communications
SPI1_SDI_PIN = GPIO12 // Rx
)
// UART pins
const (
UART0_TX_PIN = GPIO0
UART0_RX_PIN = GPIO1
UART1_TX_PIN = GPIO8
UART1_RX_PIN = GPIO9
UART_TX_PIN = UART0_TX_PIN
UART_RX_PIN = UART0_RX_PIN
)
var DefaultUART = UART0
// USB identifiers
const (
usb_STRING_PRODUCT = "Pico Plus2"
usb_STRING_MANUFACTURER = "Pimoroni"
)
var (
usb_VID uint16 = 0x2E8A
usb_PID uint16 = 0x000F
)
+11
View File
@@ -64,3 +64,14 @@ type BlockDevice interface {
// EraseBlockSize to map addresses to blocks.
EraseBlocks(start, len int64) error
}
// pad data if needed so it is long enough for correct byte alignment on writes.
func flashPad(p []byte, writeBlockSize int) []byte {
overflow := len(p) % writeBlockSize
if overflow != 0 {
for i := 0; i < writeBlockSize-overflow; i++ {
p = append(p, 0xff)
}
}
return p
}
+1 -13
View File
@@ -7,7 +7,6 @@
package machine
import (
"bytes"
"device/arm"
"device/sam"
"errors"
@@ -1917,7 +1916,7 @@ func (f flashBlockDevice) WriteAt(p []byte, off int64) (n int, err error) {
f.ensureInitComplete()
address := FlashDataStart() + uintptr(off)
padded := f.pad(p)
padded := flashPad(p, int(f.WriteBlockSize()))
waitWhileFlashBusy()
@@ -1992,17 +1991,6 @@ func (f flashBlockDevice) EraseBlocks(start, len int64) error {
return nil
}
// pad data if needed so it is long enough for correct byte alignment on writes.
func (f flashBlockDevice) pad(p []byte) []byte {
overflow := int64(len(p)) % f.WriteBlockSize()
if overflow == 0 {
return p
}
padding := bytes.Repeat([]byte{0xff}, int(f.WriteBlockSize()-overflow))
return append(p, padding...)
}
func (f flashBlockDevice) ensureInitComplete() {
if f.initComplete {
return
+1 -13
View File
@@ -7,7 +7,6 @@
package machine
import (
"bytes"
"device/arm"
"device/sam"
"errors"
@@ -2174,7 +2173,7 @@ func (f flashBlockDevice) WriteAt(p []byte, off int64) (n int, err error) {
}
address := FlashDataStart() + uintptr(off)
padded := f.pad(p)
padded := flashPad(p, int(f.WriteBlockSize()))
settings := disableFlashCache()
defer restoreFlashCache(settings)
@@ -2263,17 +2262,6 @@ func (f flashBlockDevice) EraseBlocks(start, len int64) error {
return nil
}
// pad data if needed so it is long enough for correct byte alignment on writes.
func (f flashBlockDevice) pad(p []byte) []byte {
overflow := int64(len(p)) % f.WriteBlockSize()
if overflow == 0 {
return p
}
padding := bytes.Repeat([]byte{0xff}, int(f.WriteBlockSize()-overflow))
return append(p, padding...)
}
func disableFlashCache() uint16 {
settings := sam.NVMCTRL.CTRLA.Get()
+1 -13
View File
@@ -3,7 +3,6 @@
package machine
import (
"bytes"
"device/nrf"
"internal/binary"
"runtime/interrupt"
@@ -386,7 +385,7 @@ func (f flashBlockDevice) WriteAt(p []byte, off int64) (n int, err error) {
}
address := FlashDataStart() + uintptr(off)
padded := f.pad(p)
padded := flashPad(p, int(f.WriteBlockSize()))
waitWhileFlashBusy()
@@ -444,17 +443,6 @@ func (f flashBlockDevice) EraseBlocks(start, len int64) error {
return nil
}
// pad data if needed so it is long enough for correct byte alignment on writes.
func (f flashBlockDevice) pad(p []byte) []byte {
overflow := int64(len(p)) % f.WriteBlockSize()
if overflow == 0 {
return p
}
padding := bytes.Repeat([]byte{0xff}, int(f.WriteBlockSize()-overflow))
return append(p, padding...)
}
func waitWhileFlashBusy() {
for nrf.NVMC.GetREADY() != nrf.NVMC_READY_READY_Ready {
}
+6 -1
View File
@@ -183,7 +183,12 @@ func (a *ADC) Get() uint16 {
resolutionAdjustment = 4 // 12bit
}
return rawValue.Get() << resolutionAdjustment
value := int16(rawValue.Get())
if value < 0 {
value = 0
}
return uint16(value << resolutionAdjustment)
}
// SPI on the NRF.
+2
View File
@@ -16,6 +16,8 @@ const (
// Note: On RP2350, most spinlocks are unusable due to Errata 2
_NUMSPINLOCKS = 32
_PICO_SPINLOCK_ID_IRQ = 9
// is48Pin notes whether the chip is RP2040 with 32 pins or RP2350 with 48 pins.
is48Pin = _NUMBANK0_GPIOS == 48
)
// UART on the RP2040
-12
View File
@@ -3,7 +3,6 @@
package machine
import (
"bytes"
"unsafe"
)
@@ -101,17 +100,6 @@ func (f flashBlockDevice) EraseBlocks(start, length int64) error {
return f.eraseBlocks(start, length)
}
// pad data if needed so it is long enough for correct byte alignment on writes.
func (f flashBlockDevice) pad(p []byte) []byte {
overflow := int64(len(p)) % f.WriteBlockSize()
if overflow == 0 {
return p
}
padding := bytes.Repeat([]byte{0xff}, int(f.WriteBlockSize()-overflow))
return append(p, padding...)
}
// return the correct address to be used for write
func writeAddress(off int64) uintptr {
return readAddress(off) - uintptr(memoryStart)
+1 -1
View File
@@ -230,7 +230,7 @@ func (f flashBlockDevice) writeAt(p []byte, off int64) (n int, err error) {
// e.g. real address 0x10003000 is written to at
// 0x00003000
address := writeAddress(off)
padded := f.pad(p)
padded := flashPad(p, int(f.WriteBlockSize()))
C.flash_range_write(C.uint32_t(address),
(*C.uint8_t)(unsafe.Pointer(&padded[0])),
+24
View File
@@ -9,6 +9,7 @@ import (
)
const (
cpuFreq = 200 * MHz
_NUMBANK0_GPIOS = 30
_NUMBANK0_IRQS = 4
_NUMIRQ = 32
@@ -45,6 +46,16 @@ const (
PinPIO1
)
// Analog pins on RP2040.
const (
ADC0 Pin = GPIO26
ADC1 Pin = GPIO27
ADC2 Pin = GPIO28
ADC3 Pin = GPIO29
thermADC = 30
)
const (
clkGPOUT0 clockIndex = iota // GPIO Muxing 0
clkGPOUT1 // GPIO Muxing 1
@@ -197,3 +208,16 @@ func (clks *clocksType) initTicks() {} // No ticks on RP2040
func (wd *watchdogImpl) startTick(cycles uint32) {
rp.WATCHDOG.TICK.Set(cycles | rp.WATCHDOG_TICK_ENABLE)
}
func adjustCoreVoltage() bool {
if cpuFreq <= 133*MHz {
return false
}
// The rp2040 is certified to run at 200MHz with the
// core voltage set to 1150mV.
const targetVoltage = 1150
// 0b0101 maps to 800mV and each step is 50mV.
const vreg = 0b0101 + (targetVoltage-800)/50
rp.VREG_AND_CHIP_RESET.SetVREG_VSEL(vreg)
return true
}
+13 -2
View File
@@ -9,6 +9,7 @@ import (
)
const (
cpuFreq = 150 * MHz
_NUMBANK0_GPIOS = 48
_NUMBANK0_IRQS = 6
rp2350ExtraReg = 1
@@ -126,11 +127,17 @@ func (p Pin) Configure(config PinConfig) {
return
}
p.init()
mask := uint32(1) << p
switch config.Mode {
case PinOutput:
p.setFunc(fnSIO)
rp.SIO.GPIO_OE_SET.Set(mask)
if is48Pin && p >= 32 {
mask := uint32(1) << (p % 32)
rp.SIO.GPIO_HI_OE_SET.Set(mask)
} else {
mask := uint32(1) << p
rp.SIO.GPIO_OE_SET.Set(mask)
}
case PinInput:
p.setFunc(fnSIO)
p.pulloff()
@@ -215,3 +222,7 @@ func EnterBootloader() {
func (wd *watchdogImpl) startTick(cycles uint32) {
rp.TICKS.WATCHDOG_CTRL.SetBits(1)
}
func adjustCoreVoltage() bool {
return false
}
+14
View File
@@ -0,0 +1,14 @@
//go:build rp2350 && !rp2350b
package machine
// Analog pins on RP2350a.
const (
ADC0 Pin = GPIO26
ADC1 Pin = GPIO27
ADC2 Pin = GPIO28
ADC3 Pin = GPIO29
// fifth ADC channel.
thermADC = 30
)
+48
View File
@@ -0,0 +1,48 @@
//go:build rp2350b
package machine
// RP2350B has additional pins.
const (
GPIO30 Pin = 30 // peripherals: PWM7 channel A
GPIO31 Pin = 31 // peripherals: PWM7 channel B
GPIO32 Pin = 32 // peripherals: PWM8 channel A
GPIO33 Pin = 33 // peripherals: PWM8 channel B
GPIO34 Pin = 34 // peripherals: PWM9 channel A
GPIO35 Pin = 35 // peripherals: PWM9 channel B
GPIO36 Pin = 36 // peripherals: PWM10 channel A
GPIO37 Pin = 37 // peripherals: PWM10 channel B
GPIO38 Pin = 38 // peripherals: PWM11 channel A
GPIO39 Pin = 39 // peripherals: PWM11 channel B
GPIO40 Pin = 40 // peripherals: PWM8 channel A
GPIO41 Pin = 41 // peripherals: PWM8 channel B
GPIO42 Pin = 42 // peripherals: PWM9 channel A
GPIO43 Pin = 43 // peripherals: PWM9 channel B
GPIO44 Pin = 44 // peripherals: PWM10 channel A
GPIO45 Pin = 45 // peripherals: PWM10 channel B
GPIO46 Pin = 46 // peripherals: PWM11 channel A
GPIO47 Pin = 47 // peripherals: PWM11 channel B
)
// Analog pins on 2350b.
const (
ADC0 Pin = GPIO40
ADC1 Pin = GPIO41
ADC2 Pin = GPIO42
ADC3 Pin = GPIO43
ADC4 Pin = GPIO44
ADC5 Pin = GPIO45
ADC6 Pin = GPIO46
ADC7 Pin = GPIO47
// Ninth ADC channel.
thermADC = 48
)
// Additional PWMs on the RP2350B.
var (
PWM8 = getPWMGroup(8)
PWM9 = getPWMGroup(9)
PWM10 = getPWMGroup(10)
PWM11 = getPWMGroup(11)
)
+6 -38
View File
@@ -11,15 +11,6 @@ import (
// 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
adcTempSensor // Internal temperature sensor channel
)
// Used to serialise ADC sampling
var adcLock sync.Mutex
@@ -58,20 +49,10 @@ func (a ADC) Get() uint16 {
// 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")
if a.Pin < ADC0 {
return 0, errors.New("no ADC channel for pin value")
}
return c, err
return ADCChannel(a.Pin - ADC0), nil
}
// Configure sets the channel's associated pin to analog input mode.
@@ -113,12 +94,12 @@ func ReadTemperature() (millicelsius int32) {
if rp.ADC.CS.Get()&rp.ADC_CS_EN == 0 {
InitADC()
}
thermChan, _ := ADC{Pin: thermADC}.GetADCChannel()
// Enable temperature sensor bias source
rp.ADC.CS.SetBits(rp.ADC_CS_TS_EN)
// T = 27 - (ADC_voltage - 0.706)/0.001721
return (27000<<16 - (int32(adcTempSensor.getVoltage())-706<<16)*581) >> 16
return (27000<<16 - (int32(thermChan.getVoltage())-706<<16)*581) >> 16
}
// waitForReady spins waiting for the ADC peripheral to become ready.
@@ -129,18 +110,5 @@ func waitForReady() {
// 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:
err = errors.New("no associated pin for channel")
}
return p, err
return Pin(c) + ADC0, nil
}
+35 -15
View File
@@ -10,13 +10,7 @@ import (
)
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()
return cpuFreq
}
// clockIndex identifies a hardware clock
@@ -48,6 +42,10 @@ type clock struct {
cix clockIndex
}
// The delay in seconds for core voltage adjustments to
// settle. Taken from the Pico SDK.
const _VREG_VOLTAGE_AUTO_ADJUST_DELAY = 1 / 1e3
// clock returns the clock identified by cix.
func (clks *clocksType) clock(cix clockIndex) clock {
return clock{
@@ -143,6 +141,20 @@ func (clk *clock) configure(src, auxsrc, srcFreq, freq uint32) {
}
var pllsysFB, pllsysPD1, pllsysPD2 uint32
// Compute clock dividers.
//
// Note that the entire init function is computed at compile time
// by interp.
func init() {
fb, _, pd1, pd2, err := pllSearch{LockRefDiv: 1}.CalcDivs(xoscFreq*MHz, cpuFreq, MHz)
if err != nil {
panic(err)
}
pllsysFB, pllsysPD1, pllsysPD2 = uint32(fb), uint32(pd1), uint32(pd2)
}
// init initializes the clock hardware.
//
// Must be called before any other clock function.
@@ -169,23 +181,31 @@ func (clks *clocksType) init() {
// REF FBDIV VCO POSTDIV
// pllSys: 12 / 1 = 12MHz * 125 = 1500MHZ / 6 / 2 = 125MHz
// pllUSB: 12 / 1 = 12MHz * 40 = 480 MHz / 5 / 2 = 48MHz
pllSys.init(1, 1500*MHz, 6, 2)
pllUSB.init(1, 480*MHz, 5, 2)
pllSys.init(1, pllsysFB, pllsysPD1, pllsysPD2)
pllUSB.init(1, 40, 5, 2)
// Configure clocks
// clkRef = xosc (12MHz) / 1 = 12MHz
cref := clks.clock(clkRef)
cref.configure(rp.CLOCKS_CLK_REF_CTRL_SRC_XOSC_CLKSRC,
0, // No aux mux
12*MHz,
12*MHz)
xoscFreq,
xoscFreq)
if adjustCoreVoltage() {
// Wait for the voltage to settle.
const cycles = _VREG_VOLTAGE_AUTO_ADJUST_DELAY * xoscFreq * MHz
for i := 0; i < cycles; i++ {
arm.Asm("nop")
}
}
// clkSys = pllSys (125MHz) / 1 = 125MHz
csys := clks.clock(clkSys)
csys.configure(rp.CLOCKS_CLK_SYS_CTRL_SRC_CLKSRC_CLK_SYS_AUX,
rp.CLOCKS_CLK_SYS_CTRL_AUXSRC_CLKSRC_PLL_SYS,
125*MHz,
125*MHz)
cpuFreq,
cpuFreq)
// clkUSB = pllUSB (48MHz) / 1 = 48MHz
cusb := clks.clock(clkUSB)
@@ -209,8 +229,8 @@ func (clks *clocksType) init() {
cperi := clks.clock(clkPeri)
cperi.configure(0,
rp.CLOCKS_CLK_PERI_CTRL_AUXSRC_CLK_SYS,
125*MHz,
125*MHz)
cpuFreq,
cpuFreq)
clks.initTicks()
}
+32 -8
View File
@@ -33,6 +33,7 @@ type irqSummary struct {
type ioBank0Type struct {
io [_NUMBANK0_GPIOS]ioType
_ [rp2350ExtraReg][128]byte
irqsum [rp2350ExtraReg]irqSummary
intR [_NUMBANK0_IRQS]volatile.Register32
proc0IRQctrl irqCtrl
@@ -63,8 +64,13 @@ func (p Pin) PortMaskSet() (*uint32, uint32) {
// set drives the pin high
func (p Pin) set() {
mask := uint32(1) << p
rp.SIO.GPIO_OUT_SET.Set(mask)
if is48Pin && p >= 32 {
mask := uint32(1) << (p % 32)
rp.SIO.GPIO_HI_OUT_SET.Set(mask)
} else {
mask := uint32(1) << p
rp.SIO.GPIO_OUT_SET.Set(mask)
}
}
func (p Pin) PortMaskClear() (*uint32, uint32) {
@@ -73,18 +79,31 @@ func (p Pin) PortMaskClear() (*uint32, uint32) {
// clr drives the pin low
func (p Pin) clr() {
mask := uint32(1) << p
rp.SIO.GPIO_OUT_CLR.Set(mask)
if is48Pin && p >= 32 {
mask := uint32(1) << (p % 32)
rp.SIO.GPIO_HI_OUT_CLR.Set(mask)
} else {
mask := uint32(1) << p
rp.SIO.GPIO_OUT_CLR.Set(mask)
}
}
// xor toggles the pin
func (p Pin) xor() {
mask := uint32(1) << p
rp.SIO.GPIO_OUT_XOR.Set(mask)
if is48Pin && p >= 32 {
mask := uint32(1) << (p % 32)
rp.SIO.GPIO_HI_OUT_XOR.Set(mask)
} else {
mask := uint32(1) << p
rp.SIO.GPIO_OUT_XOR.Set(mask)
}
}
// get returns the pin value
func (p Pin) get() bool {
if is48Pin && p >= 32 {
return rp.SIO.GPIO_HI_IN.HasBits(1 << (p % 32))
}
return rp.SIO.GPIO_IN.HasBits(1 << p)
}
@@ -134,8 +153,13 @@ func (p Pin) setFunc(fn pinFunc) {
// init initializes the gpio pin
func (p Pin) init() {
mask := uint32(1) << p
rp.SIO.GPIO_OE_CLR.Set(mask)
if is48Pin && p >= 32 {
mask := uint32(1) << (p % 32)
rp.SIO.GPIO_HI_OE_CLR.Set(mask)
} else {
mask := uint32(1) << p
rp.SIO.GPIO_OE_CLR.Set(mask)
}
p.clr()
}
+1 -7
View File
@@ -1,4 +1,4 @@
//go:build rp2040 || rp2350 || ae_rp2040 || badger2040 || challenger_rp2040 || feather_rp2040 || gopher_badge || kb2040 || macropad_rp2040 || nano_rp2040 || pico || qtpy_rp2040 || thingplus_rp2040 || thumby || tufty2040 || waveshare_rp2040_zero || xiao_rp2040
//go:build rp2040 || rp2350 || gopher_badge || pico
package machine
@@ -34,10 +34,4 @@ const (
GPIO27 Pin = 27 // peripherals: PWM5 channel B
GPIO28 Pin = 28 // peripherals: PWM6 channel A
GPIO29 Pin = 29 // peripherals: PWM6 channel B
// Analog pins
ADC0 Pin = GPIO26
ADC1 Pin = GPIO27
ADC2 Pin = GPIO28
ADC3 Pin = GPIO29
)
+183 -4
View File
@@ -4,6 +4,9 @@ package machine
import (
"device/rp"
"errors"
"math"
"math/bits"
"runtime/volatile"
"unsafe"
)
@@ -29,12 +32,11 @@ var (
// Post Divider 1, postDiv1 with range 1-7 and be >= postDiv2.
//
// Post Divider 2, postDiv2 with range 1-7.
func (pll *pll) init(refdiv, vcoFreq, postDiv1, postDiv2 uint32) {
func (pll *pll) init(refdiv, fbdiv, postDiv1, postDiv2 uint32) {
refFreq := xoscFreq / refdiv
// What are we multiplying the reference clock by to get the vco freq
// (The regs are called div, because you divide the vco output and compare it to the refclk)
fbdiv := vcoFreq / (refFreq * MHz)
// Check fbdiv range
if !(fbdiv >= 16 && fbdiv <= 320) {
@@ -54,13 +56,14 @@ func (pll *pll) init(refdiv, vcoFreq, postDiv1, postDiv2 uint32) {
panic("postdiv1 should be greater than or equal to postdiv2")
}
// Check that reference frequency is no greater than vco / 16
// Check that reference frequency is no greater than vcoFreq / 16
vcoFreq := calcVCO(xoscFreq, fbdiv, refdiv)
if refFreq > vcoFreq/16 {
panic("reference frequency should not be greater than vco frequency divided by 16")
}
// div1 feeds into div2 so if div1 is 5 and div2 is 2 then you get a divide by 10
pdiv := postDiv1<<rp.PLL_SYS_PRIM_POSTDIV1_Pos | postDiv2<<rp.PLL_SYS_PRIM_POSTDIV2_Pos
pdiv := uint32(postDiv1)<<rp.PLL_SYS_PRIM_POSTDIV1_Pos | uint32(postDiv2)<<rp.PLL_SYS_PRIM_POSTDIV2_Pos
if pll.cs.HasBits(rp.PLL_SYS_CS_LOCK) &&
refdiv == pll.cs.Get()&rp.PLL_SYS_CS_REFDIV_Msk &&
@@ -98,3 +101,179 @@ func (pll *pll) init(refdiv, vcoFreq, postDiv1, postDiv2 uint32) {
pll.pwr.ClearBits(rp.PLL_SYS_PWR_POSTDIVPD)
}
var errVCOOverflow = errors.New("VCO calculation overflow; use lower MHz")
// pllSearch enables searching for a good PLL configuration.
// Example for 12MHz crystal and RP2040:
//
// fbdiv, refdiv, pd1, pd2, _ := pllSearch{LockRefDiv:1}.CalcDivs(12*MHz, 125*MHz, MHz)
//
// Example for 12MHz crystal and RP2350:
//
// fbdiv, refdiv, pd1, pd2, _ := pllSearch{LockRefDiv:1}.CalcDivs(12*MHz, 150*MHz, MHz)
type pllSearch struct {
LowerVCO bool
LockRefDiv uint8
}
func (ps pllSearch) CalcDivs(xoscRef, targetFreq, MHz uint64) (fbdiv uint64, refdiv, pd1, pd2 uint8, err error) {
genTable()
var bestFreq, bestFbdiv uint64
var bestRefdiv, bestpd1, bestpd2 uint8
maxVCO, minVCO := 1600*MHz, 750*MHz
var bestMargin int64 = int64(maxVCO)
iters := 0
for refdiv = 1; refdiv < 64; refdiv++ {
if ps.LockRefDiv != 0 && refdiv != ps.LockRefDiv {
continue
}
firstFBDiv := minVCO * uint64(refdiv) / xoscRef
for fbdiv = firstFBDiv; fbdiv < 321; fbdiv++ {
overflow, vco := bits.Mul64(xoscRef, fbdiv)
vco /= uint64(refdiv)
if overflow != 0 {
return fbdiv, refdiv, pd1, pd2, errVCOOverflow
} else if vco > maxVCO {
break
}
calcPD12 := vco / targetFreq
if calcPD12 < 1 {
calcPD12 = 1
} else if calcPD12 > 49 {
calcPD12 = 49
}
iters++
pd1 = pdTable[calcPD12].hivco[0]
pd2 = pdTable[calcPD12].hivco[1]
fout, err := pllFreqOutPostdiv(xoscRef, fbdiv, MHz, refdiv, pd1, pd2)
found := false
margin := abs(int64(fout) - int64(targetFreq))
if err == nil && margin <= bestMargin {
found = true
bestFreq = fout
bestFbdiv = fbdiv
bestpd1 = pd1
bestpd2 = pd2
bestRefdiv = refdiv
bestMargin = margin
}
pd1 = pdTable[calcPD12].lovco[0]
pd2 = pdTable[calcPD12].lovco[1]
fout, err = pllFreqOutPostdiv(xoscRef, fbdiv, MHz, refdiv, pd1, pd2)
margin = abs(int64(fout) - int64(targetFreq))
if err == nil && margin <= bestMargin {
found = true
bestFreq = fout
bestFbdiv = fbdiv
bestpd1 = pd1
bestpd2 = pd2
bestRefdiv = refdiv
bestMargin = margin
}
if found && ps.LowerVCO {
break
}
}
}
if bestFreq == 0 {
return fbdiv, refdiv, pd1, pd2, errors.New("no best frequency found")
}
return bestFbdiv, bestRefdiv, bestpd1, bestpd2, nil
}
func abs(a int64) int64 {
if a == math.MinInt64 {
return math.MaxInt64
} else if a < 0 {
return -a
}
return a
}
func pllFreqOutPostdiv(xosc, fbdiv, MHz uint64, refdiv, postdiv1, postdiv2 uint8) (foutpostdiv uint64, err error) {
// testing grounds.
const (
mhz = 1
cfref = 12 * mhz // given by crystal oscillator selection.
crefd = 1
cfbdiv = 100
cvco = cfref * cfbdiv / crefd
cpd1 = 6
cpd2 = 2
foutpd = (cfref / crefd) * cfbdiv / (cpd1 * cpd2)
)
refFreq := xosc / uint64(refdiv)
overflow, vco := bits.Mul64(xosc, fbdiv)
vco /= uint64(refdiv)
foutpostdiv = vco / uint64(postdiv1*postdiv2)
switch {
case refdiv < 1 || refdiv > 63:
err = errors.New("reference divider out of range")
case fbdiv < 16 || fbdiv > 320:
err = errors.New("feedback divider out of range")
case postdiv1 < 1 || postdiv1 > 7:
err = errors.New("postdiv1 out of range")
case postdiv2 < 1 || postdiv2 > 7:
err = errors.New("postdiv2 out of range")
case postdiv1 < postdiv2:
err = errors.New("user error: use higher value for postdiv1 for lower power consumption")
case vco < 750*MHz || vco > 1600*MHz:
err = errors.New("VCO out of range")
case refFreq < 5*MHz:
err = errors.New("minimum reference frequency breach")
case refFreq > vco/16:
err = errors.New("maximum reference frequency breach")
case vco > 1200*MHz && vco < 1600*MHz && xosc < 75*MHz && refdiv != 1:
err = errors.New("refdiv should be 1 for given VCO and reference frequency")
case overflow != 0:
err = errVCOOverflow
}
if err != nil {
return 0, err
}
return foutpostdiv, nil
}
func calcVCO(xoscFreq, fbdiv, refdiv uint32) uint32 {
const maxXoscMHz = math.MaxUint32 / 320 / MHz // 13MHz maximum xosc apparently.
if fbdiv > 320 || xoscFreq > math.MaxUint32/320 {
panic("invalid VCO calculation args")
}
return xoscFreq * fbdiv / refdiv
}
var pdTable = [50]struct {
hivco [2]uint8
lovco [2]uint8
}{}
func genTable() {
if pdTable[1].hivco[1] != 0 {
return // Already generated.
}
for product := 1; product < len(pdTable); product++ {
bestProdhi := 255
bestProdlo := 255
for pd1 := 7; pd1 > 0; pd1-- {
for pd2 := pd1; pd2 > 0; pd2-- {
gotprod := pd1 * pd2
if abs(int64(gotprod-product)) < abs(int64(bestProdlo-product)) {
bestProdlo = gotprod
pdTable[product].lovco[0] = uint8(pd1)
pdTable[product].lovco[1] = uint8(pd2)
}
}
}
for pd1 := 1; pd1 < 8; pd1++ {
for pd2 := 1; pd2 <= pd1; pd2++ {
gotprod := pd1 * pd2
if abs(int64(gotprod-product)) < abs(int64(bestProdhi-product)) {
bestProdhi = gotprod
pdTable[product].hivco[0] = uint8(pd1)
pdTable[product].hivco[1] = uint8(pd2)
}
}
}
}
}
@@ -1,4 +1,4 @@
//go:build rp2040
//go:build rp2040 || rp2350
package machine
@@ -15,7 +15,7 @@ var (
)
const (
maxPWMPins = 29
maxPWMPins = _NUMBANK0_GPIOS - 1
)
// pwmGroup is one PWM peripheral, which consists of a counter and two output
@@ -146,12 +146,14 @@ func (p *pwmGroup) Counter() uint32 {
// Period returns the used PWM period in nanoseconds.
func (p *pwmGroup) Period() uint64 {
periodPerCycle := cpuPeriod()
// Lines below can overflow if operations done without care.
// maxInt=255, maxFrac=15, maxTop=65536, maxPHC=1 => maxProduct= (16*255+15) * (65536*2*1e9) = 5.3673e17 < MaxUint64=1.8e19 (close call.)
const compileTimeCheckPeriod uint64 = (255*16 + 15) * (65535 + 1) * 2 * 1e9
freq := uint64(CPUFrequency())
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 (16*uint64(Int) + uint64(frac)) * uint64((top+1)*(phc+1)*1e9) / (16 * freq) // cycles = (TOP+1) * (CSRPHCorrect + 1) * (DIV_INT + DIV_FRAC/16)
}
// SetInverting sets whether to invert the output of this channel.
@@ -266,6 +268,9 @@ func (pwm *pwmGroup) setPeriod(period uint64) error {
// 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
// This will be a compile time error if this method is at risk of overflowing. cpufreq=155MHz for typical RP2350.
maxCPUFreq = 4 * GHz // Can go up to 4GHz without overflowing :)
compileTimeCheckSetPeriod uint64 = 16 * maxPeriod * maxCPUFreq
)
if period > maxPeriod || period < 8 {
@@ -279,11 +284,13 @@ func (pwm *pwmGroup) setPeriod(period uint64) error {
// DIV_INT + DIV_FRAC/16 = cycles / ( (TOP+1) * (CSRPHCorrect+1) ) // DIV_FRAC/16 is always 0 in this equation
// 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
var (
freq = uint64(CPUFrequency())
phc = uint64(pwm.getPhaseCorrect())
rhs = 16 * period * freq / ((1 + phc) * 1e9 * (1 + topStart)) // right-hand-side of equation, scaled so frac is not divided
whole = rhs / 16
frac = rhs % 16
)
switch {
case whole > 0xff:
whole = 0xff
@@ -296,7 +303,7 @@ func (pwm *pwmGroup) setPeriod(period uint64) error {
// 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
top := 16*period*freq/((1+phc)*1e9*(16*whole+frac)) - 1
if top > maxTop {
top = maxTop
}
@@ -400,6 +407,9 @@ func (pwm *pwmGroup) getClockDiv() (Int, frac uint8) {
// pwmGPIOToSlice Determine the PWM channel that is attached to the specified GPIO.
// gpio must be less than 30. Returns the PWM slice number that controls the specified GPIO.
func pwmGPIOToSlice(gpio Pin) (slicenum uint8) {
if is48Pin && gpio >= 32 {
return uint8(8 + ((gpio-32)/2)%4)
}
return (uint8(gpio) >> 1) & 7
}
+3 -3
View File
@@ -104,13 +104,13 @@ func (spi SPI) Transfer(w byte) (byte, error) {
}
func (spi SPI) SetBaudRate(br uint32) error {
const freqin uint32 = 125 * MHz
const maxBaud uint32 = 66.5 * MHz // max output frequency is 66.5MHz on rp2040. see Note page 527.
// Find smallest prescale value which puts output frequency in range of
// post-divide. Prescale is an even number from 2 to 254 inclusive.
var prescale, postdiv uint32
freq := CPUFrequency()
for prescale = 2; prescale < 255; prescale += 2 {
if freqin < (prescale+2)*256*br {
if freq < (prescale+2)*256*br {
break
}
}
@@ -120,7 +120,7 @@ func (spi SPI) SetBaudRate(br uint32) error {
// Find largest post-divide which makes output <= baudrate. Post-divide is
// an integer in the range 1 to 256 inclusive.
for postdiv = 256; postdiv > 1; postdiv-- {
if freqin/(prescale*(postdiv-1)) > br {
if freq/(prescale*(postdiv-1)) > br {
break
}
}
+4 -4
View File
@@ -67,7 +67,7 @@ func (uart *UART) Configure(config UARTConfig) error {
uart.Interrupt.SetPriority(0x80)
uart.Interrupt.Enable()
// setup interrupt on receive
// Setup interrupt on receive.
uart.Bus.UARTIMSC.Set(rp.UART0_UARTIMSC_RXIM)
return nil
@@ -75,7 +75,7 @@ func (uart *UART) Configure(config UARTConfig) error {
// SetBaudRate sets the baudrate to be used for the UART.
func (uart *UART) SetBaudRate(br uint32) {
div := 8 * 125 * MHz / br
div := 8 * CPUFrequency() / br
ibrd := div >> 7
var fbrd uint32
@@ -153,7 +153,7 @@ func initUART(uart *UART) {
// handleInterrupt should be called from the appropriate interrupt handler for
// this UART instance.
func (uart *UART) handleInterrupt(interrupt.Interrupt) {
for uart.Bus.UARTFR.HasBits(rp.UART0_UARTFR_RXFE) {
for !uart.Bus.UARTFR.HasBits(rp.UART0_UARTFR_RXFE) {
uart.Receive(byte((uart.Bus.UARTDR.Get() & 0xFF)))
}
uart.Receive(byte((uart.Bus.UARTDR.Get() & 0xFF)))
}
+2 -13
View File
@@ -5,7 +5,6 @@ package machine
import (
"device/stm32"
"bytes"
"unsafe"
)
@@ -41,7 +40,8 @@ func (f flashBlockDevice) WriteAt(p []byte, off int64) (n int, err error) {
unlockFlash()
defer lockFlash()
return writeFlashData(FlashDataStart()+uintptr(off), f.pad(p))
p = flashPad(p, int(f.WriteBlockSize()))
return writeFlashData(FlashDataStart()+uintptr(off), p)
}
// Size returns the number of bytes in this block device.
@@ -90,17 +90,6 @@ func (f flashBlockDevice) EraseBlocks(start, len int64) error {
return nil
}
// pad data if needed so it is long enough for correct byte alignment on writes.
func (f flashBlockDevice) pad(p []byte) []byte {
overflow := int64(len(p)) % f.WriteBlockSize()
if overflow == 0 {
return p
}
padding := bytes.Repeat([]byte{0xff}, int(f.WriteBlockSize()-overflow))
return append(p, padding...)
}
const memoryStart = 0x08000000
func unlockFlash() {
+2 -2
View File
@@ -1,9 +1,9 @@
package descriptor
import (
"bytes"
"errors"
"internal/binary"
"internal/bytealg"
)
var configurationCDCHID = [configurationTypeLen]byte{
@@ -87,7 +87,7 @@ func FindClassHIDType(des, class []byte) (ClassHIDType, error) {
// search only for ClassHIDType without the ClassLength,
// in case it has already been set.
idx := bytes.Index(des, class[:ClassHIDTypeLen-2])
idx := bytealg.Index(des, class[:ClassHIDTypeLen-2])
if idx == -1 {
return ClassHIDType{}, errNoClassHIDFound
}
+189
View File
@@ -0,0 +1,189 @@
//go:build tinygo.riscv32 && virt
// Machine implementation for VirtIO targets.
// At the moment only QEMU RISC-V is supported, but support for ARM for example
// should not be difficult to add with a change to virtioFindDevice.
package machine
import (
"errors"
"runtime/volatile"
"sync"
"unsafe"
)
const deviceName = "riscv-qemu"
func (p Pin) Set(high bool) {
// no pins defined
}
var rngLock sync.Mutex
var rngDevice *virtioDevice1
var rngBuf volatile.Register32
var errNoRNG = errors.New("machine: no entropy source found")
var errNoRNGData = errors.New("machine: entropy source didn't return enough data")
// GetRNG returns random numbers from a VirtIO entropy source.
// When running in QEMU, it requires adding the RNG device:
//
// -device virtio-rng-device
func GetRNG() (uint32, error) {
rngLock.Lock()
// Initialize the device on first use.
if rngDevice == nil {
// Search for an available RNG.
rngDevice = virtioFindDevice(virtioDeviceEntropySource)
if rngDevice == nil {
rngLock.Unlock()
return 0, errNoRNG
}
// Initialize the device.
rngDevice.status.Set(0) // reset device
rngDevice.status.Set(virtioDeviceStatusAcknowledge)
rngDevice.status.Set(virtioDeviceStatusAcknowledge | virtioDeviceStatusDriver)
rngDevice.hostFeaturesSel.Set(0)
rngDevice.status.Set(virtioDeviceStatusAcknowledge | virtioDeviceStatusDriver | virtioDeviceStatusDriverOk)
rngDevice.guestPageSize.Set(4096)
// Configure queue, according to section 4.2.4 "Legacy interface".
// Note: we're skipping checks for queuePFM and queueNumMax.
rngDevice.queueSel.Set(0) // use queue 0 (the only queue)
rngDevice.queueNum.Set(1) // use a single buffer in the queue
rngDevice.queueAlign.Set(4096) // default alignment appears to be 4096
rngDevice.queuePFN.Set(uint32(uintptr(unsafe.Pointer(&rngQueue))) / 4096)
// Configure the only buffer in the queue (but don't increment
// rngQueue.available yet).
rngQueue.buffers[0].address = uint64(uintptr(unsafe.Pointer(&rngBuf)))
rngQueue.buffers[0].length = uint32(unsafe.Sizeof(rngBuf))
rngQueue.buffers[0].flags = 2 // 2 means write-only buffer
}
// Increment the available ring buffer. This doesn't actually change the
// buffer index (it's a ring with a single entry), but the number needs to
// be incremented otherwise the device won't recognize a new buffer.
index := rngQueue.available.index
rngQueue.available.index = index + 1
rngDevice.queueNotify.Set(0) // notify the device of the 'new' (reused) buffer
for rngQueue.used.index.Get() != index+1 {
// Busy wait until the RNG buffer is filled.
// A better way would be to wait for an interrupt, but since this driver
// implementation is mostly used for testing it's good enough for now.
}
// Check that we indeed got 4 bytes back.
if rngQueue.used.ring[0].length != 4 {
rngLock.Unlock()
return 0, errNoRNGData
}
// Read the resulting random numbers.
result := rngBuf.Get()
rngLock.Unlock()
return result, nil
}
// Implement a driver for the VirtIO entropy device.
// https://docs.oasis-open.org/virtio/virtio/v1.2/csd01/virtio-v1.2-csd01.html
// http://wiki.osdev.org/Virtio
// http://www.dumais.io/index.php?article=aca38a9a2b065b24dfa1dee728062a12
const (
virtioDeviceStatusAcknowledge = 1
virtioDeviceStatusDriver = 2
virtioDeviceStatusDriverOk = 4
virtioDeviceStatusFeaturesOk = 8
virtioDeviceStatusFailed = 128
)
const (
virtioDeviceReserved = iota
virtioDeviceNetworkCard
virtioDeviceBlockDevice
virtioDeviceConsole
virtioDeviceEntropySource
// there are more device types
)
// VirtIO device version 1
type virtioDevice1 struct {
magic volatile.Register32 // always 0x74726976
version volatile.Register32
deviceID volatile.Register32
vendorID volatile.Register32
hostFeatures volatile.Register32
hostFeaturesSel volatile.Register32
_ [2]uint32
guestFeatures volatile.Register32
guestFeaturesSel volatile.Register32
guestPageSize volatile.Register32
_ uint32
queueSel volatile.Register32
queueNumMax volatile.Register32
queueNum volatile.Register32
queueAlign volatile.Register32
queuePFN volatile.Register32
_ [3]uint32
queueNotify volatile.Register32
_ [3]uint32
interruptStatus volatile.Register32
interruptAck volatile.Register32
_ [2]uint32
status volatile.Register32
}
// VirtIO queue, with a single buffer.
type virtioQueue struct {
buffers [1]struct {
address uint64
length uint32
flags uint16
next uint16
} // 16 bytes
available struct {
flags uint16
index uint16
ring [1]uint16
eventIndex uint16
} // 8 bytes
_ [4096 - 16*1 - 8*1]byte // padding (to align on a 4096 byte boundary)
used struct {
flags uint16
index volatile.Register16
ring [1]struct {
index uint32
length uint32
}
availEvent uint16
}
}
func virtioFindDevice(deviceID uint32) *virtioDevice1 {
// On RISC-V, QEMU defines 8 VirtIO devices starting at 0x10001000 and
// repeating every 0x1000 bytes.
// The memory map can be seen in the QEMU source code:
// https://github.com/qemu/qemu/blob/master/hw/riscv/virt.c
for i := 0; i < 8; i++ {
dev := (*virtioDevice1)(unsafe.Pointer(uintptr(0x10001000 + i*0x1000)))
if dev.magic.Get() != 0x74726976 || dev.version.Get() != 1 || dev.deviceID.Get() != deviceID {
continue
}
return dev
}
return nil
}
// A VirtIO queue needs to be page-aligned.
//
//go:align 4096
var rngQueue virtioQueue
+1 -1
Submodule src/net updated: a237059610...ca7cd08f85
+22
View File
@@ -307,6 +307,28 @@ func (f *File) Sync() (err error) {
return
}
// Chmod changes the mode of the file to mode. If there is an error, it will be
// of type *PathError.
func (f *File) Chmod(mode FileMode) (err error) {
if f.handle == nil {
err = ErrClosed
} else {
err = f.chmod(mode)
}
return
}
// Chdir changes the current working directory to the file, which must be a
// directory. If there is an error, it will be of type *PathError.
func (f *File) Chdir() (err error) {
if f.handle == nil {
err = ErrClosed
} else {
err = f.chdir()
}
return
}
// LinkError records an error during a link or symlink or rename system call and
// the paths that caused it.
type LinkError struct {
+18
View File
@@ -42,6 +42,12 @@ func NewFile(fd uintptr, name string) *File {
return &File{&file{handle: stdioFileHandle(fd), name: name}}
}
// Chdir changes the current working directory to the named directory.
// If there is an error, it will be of type *PathError.
func Chdir(dir string) error {
return ErrNotImplemented
}
// Rename renames (moves) oldpath to newpath.
// If newpath already exists and is not a directory, Rename replaces it.
// OS-specific restrictions may apply when oldpath and newpath are in different directories.
@@ -128,6 +134,10 @@ func Pipe() (r *File, w *File, err error) {
return nil, nil, ErrNotImplemented
}
func Symlink(oldname, newname string) error {
return ErrNotImplemented
}
func Readlink(name string) (string, error) {
return "", ErrNotImplemented
}
@@ -149,3 +159,11 @@ func (f *File) Truncate(size int64) (err error) {
return Truncate(f.name, size)
}
func (f *File) chmod(mode FileMode) error {
return ErrUnsupported
}
func (f *File) chdir() error {
return ErrNotImplemented
}
+31
View File
@@ -151,6 +151,37 @@ func (f *File) Truncate(size int64) (err error) {
return Truncate(f.name, size)
}
func (f *File) chmod(mode FileMode) error {
if f.handle == nil {
return ErrClosed
}
longName := fixLongPath(f.name)
e := ignoringEINTR(func() error {
return syscall.Chmod(longName, syscallMode(mode))
})
if e != nil {
return &PathError{Op: "chmod", Path: f.name, Err: e}
}
return nil
}
func (f *File) chdir() error {
if f.handle == nil {
return ErrClosed
}
// TODO: use syscall.Fchdir instead
longName := fixLongPath(f.name)
e := ignoringEINTR(func() error {
return syscall.Chdir(longName)
})
if e != nil {
return &PathError{Op: "chdir", Path: f.name, Err: e}
}
return nil
}
// ReadAt reads up to len(b) bytes from the File starting at the given absolute offset.
// It returns the number of bytes read and any error encountered, possibly io.EOF.
// At end of file, Pread returns 0, io.EOF.
+8
View File
@@ -142,3 +142,11 @@ func isWindowsNulName(name string) bool {
}
return true
}
func (f *File) chmod(mode FileMode) error {
return ErrNotImplemented
}
func (f *File) chdir() error {
return ErrNotImplemented
}
+78
View File
@@ -271,6 +271,84 @@ func (v Value) Comparable() bool {
}
}
// Equal reports true if v is equal to u.
// For two invalid values, Equal will report true.
// For an interface value, Equal will compare the value within the interface.
// Otherwise, If the values have different types, Equal will report false.
// Otherwise, for arrays and structs Equal will compare each element in order,
// and report false if it finds non-equal elements.
// During all comparisons, if values of the same type are compared,
// and the type is not comparable, Equal will panic.
//
// Copyright 2009 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.
func (v Value) Equal(u Value) bool {
if v.Kind() == Interface {
v = v.Elem()
}
if u.Kind() == Interface {
u = u.Elem()
}
if !v.IsValid() || !u.IsValid() {
return v.IsValid() == u.IsValid()
}
if v.Kind() != u.Kind() || v.Type() != u.Type() {
return false
}
// Handle each Kind directly rather than calling valueInterface
// to avoid allocating.
switch v.Kind() {
default:
panic("reflect.Value.Equal: invalid Kind")
case Bool:
return v.Bool() == u.Bool()
case Int, Int8, Int16, Int32, Int64:
return v.Int() == u.Int()
case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
return v.Uint() == u.Uint()
case Float32, Float64:
return v.Float() == u.Float()
case Complex64, Complex128:
return v.Complex() == u.Complex()
case String:
return v.String() == u.String()
case Chan, Pointer, UnsafePointer:
return v.Pointer() == u.Pointer()
case Array:
// u and v have the same type so they have the same length
vl := v.Len()
if vl == 0 {
// panic on [0]func()
if !v.Type().Elem().Comparable() {
break
}
return true
}
for i := 0; i < vl; i++ {
if !v.Index(i).Equal(u.Index(i)) {
return false
}
}
return true
case Struct:
// u and v have the same type so they have the same fields
nf := v.NumField()
for i := 0; i < nf; i++ {
if !v.Field(i).Equal(u.Field(i)) {
return false
}
}
return true
case Func, Map, Slice:
break
}
panic("reflect.Value.Equal: values of type " + v.Type().String() + " are not comparable")
}
func (v Value) Addr() Value {
if !v.CanAddr() {
panic("reflect.Value.Addr of unaddressable value")
+3 -3
View File
@@ -23,13 +23,13 @@ func fastrand() uint32 {
return xorshift32State
}
func init() {
func initRand() {
r, _ := hardwareRand()
xorshift64State = uint64(r | 1) // protect against 0
xorshift32State = uint32(xorshift64State)
}
var xorshift32State uint32
var xorshift32State uint32 = 1
func xorshift32(x uint32) uint32 {
// Algorithm "xor" from p. 4 of Marsaglia, "Xorshift RNGs".
@@ -49,7 +49,7 @@ func fastrand64() uint64 {
return xorshift64State
}
var xorshift64State uint64
var xorshift64State uint64 = 1
// 64-bit xorshift multiply rng from http://vigna.di.unimi.it/ftp/papers/xorshift.pdf
func xorshiftMult64(x uint64) uint64 {
+5
View File
@@ -226,3 +226,8 @@ func divideByZeroPanic() {
func blockingPanic() {
runtimePanicAt(returnAddress(0), "trying to do blocking operation in exported function")
}
//go:linkname fips_fatal crypto/internal/fips140.fatal
func fips_fatal(msg string) {
runtimePanic(msg)
}
+1 -1
View File
@@ -1,4 +1,4 @@
//go:build baremetal && (nrf || (stm32 && !(stm32f103 || stm32l0x1)) || (sam && atsamd51) || (sam && atsame5x) || esp32c3 || tkey)
//go:build baremetal && (nrf || (stm32 && !(stm32f103 || stm32l0x1)) || (sam && atsamd51) || (sam && atsame5x) || esp32c3 || tkey || (tinygo.riscv32 && virt))
// If you update the above build constraint, you'll probably also need to update
// src/crypto/rand/rand_baremetal.go.
+1 -1
View File
@@ -1,4 +1,4 @@
//go:build baremetal && !(nrf || (stm32 && !(stm32f103 || stm32l0x1)) || (sam && atsamd51) || (sam && atsame5x) || esp32c3 || tkey)
//go:build baremetal && !(nrf || (stm32 && !(stm32f103 || stm32l0x1)) || (sam && atsamd51) || (sam && atsame5x) || esp32c3 || tkey || (tinygo.riscv32 && virt))
package runtime
+10
View File
@@ -35,6 +35,7 @@ func wasmEntryReactor() {
heapStart = uintptr(unsafe.Pointer(&heapStartSymbol))
heapEnd = uintptr(wasm_memory_size(0) * wasmPageSize)
initHeap()
initRand()
if hasScheduler {
// A package initializer might do funky stuff like start a goroutine and
@@ -51,6 +52,15 @@ func wasmEntryReactor() {
}
}
// This is the _start entry point, when using -buildmode=wasi-legacy.
func wasmEntryLegacy() {
// These need to be initialized early so that the heap can be initialized.
initializeCalled = true
heapStart = uintptr(unsafe.Pointer(&heapStartSymbol))
heapEnd = uintptr(wasm_memory_size(0) * wasmPageSize)
run()
}
// Whether the runtime was initialized by a call to _initialize or _start.
var initializeCalled bool
+11
View File
@@ -31,3 +31,14 @@ func scheduleLogChan(msg string, ch *channel, t *task.Task) {
func Goexit() {
panicOrGoexit(nil, panicGoexit)
}
//go:linkname fips_getIndicator crypto/internal/fips140.getIndicator
func fips_getIndicator() uint8 {
return task.Current().FipsIndicator
}
//go:linkname fips_setIndicator crypto/internal/fips140.setIndicator
func fips_setIndicator(indicator uint8) {
// This indicator is stored per goroutine.
task.Current().FipsIndicator = indicator
}
+1
View File
@@ -247,6 +247,7 @@ func sleep(duration int64) {
// With a scheduler, init and the main function are invoked in a goroutine before starting the scheduler.
func run() {
initHeap()
initRand()
go func() {
initAll()
callMain()
+1
View File
@@ -13,6 +13,7 @@ const hasParallelism = false
// With the "none" scheduler, init and the main function are invoked directly.
func run() {
initHeap()
initRand()
initAll()
callMain()
mainExited = true
+15
View File
@@ -0,0 +1,15 @@
package runtime
// Dummy implementation of synctest functions (we don't support synctest at the
// moment).
//go:linkname synctest_acquire internal/synctest.acquire
func synctest_acquire() any {
// Dummy: we don't support synctest.
return nil
}
//go:linkname synctest_release internal/synctest.release
func synctest_release(sg any) {
// Dummy: we don't support synctest.
}
+13
View File
@@ -1,5 +1,18 @@
package runtime
//go:linkname time_runtimeNano time.runtimeNano
func time_runtimeNano() int64 {
// Note: we're ignoring sync groups here (package testing/synctest).
// See: https://github.com/golang/go/issues/67434
return nanotime()
}
//go:linkname time_runtimeNow time.runtimeNow
func time_runtimeNow() (sec int64, nsec int32, mono int64) {
// Also ignoring the sync group here, like time_runtimeNano above.
return now()
}
// timerNode is an element in a linked list of timers.
type timerNode struct {
next *timerNode
+4
View File
@@ -233,6 +233,10 @@ func (w WaitStatus) Continued() bool { return false }
func (w WaitStatus) StopSignal() Signal { return 0 }
func (w WaitStatus) TrapCause() int { return 0 }
// Purely here for compatibility.
type Rusage struct {
}
// since rusage is quite a big struct and we stub it out anyway no need to define it here
func Wait4(pid int, wstatus *WaitStatus, options int, rusage uintptr) (wpid int, err error) {
return 0, ENOSYS // TODO
+15
View File
@@ -120,8 +120,11 @@ const (
SYS_FCNTL64
SYS_FSTATAT64
SYS_IOCTL
SYS_MKDIRAT
SYS_OPENAT
SYS_READLINKAT
SYS_UNLINKAT
SYS_WAITID
PATH_MAX = 4096
)
@@ -438,6 +441,13 @@ type RawSockaddrInet6 struct {
// stub
}
func RandomGet(b []byte) error {
if len(b) > 0 {
libc_arc4random_buf(unsafe.Pointer(&b[0]), uint(len(b)))
}
return nil
}
// This is a stub, it is not functional.
func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
@@ -483,3 +493,8 @@ func libc_fdclosedir(unsafe.Pointer) int32
//
//export readdir
func libc_readdir(unsafe.Pointer) *Dirent
// void arc4random_buf(void *buf, size_t buflen);
//
//export arc4random_buf
func libc_arc4random_buf(buf unsafe.Pointer, buflen uint)
+45
View File
@@ -17,6 +17,8 @@ import (
"io/fs"
"math/rand"
"os"
"path/filepath"
"runtime"
"strconv"
"strings"
"time"
@@ -390,6 +392,49 @@ func (c *common) Setenv(key, value string) {
}
}
// Chdir calls os.Chdir(dir) and uses Cleanup to restore the current
// working directory to its original value after the test. On Unix, it
// also sets PWD environment variable for the duration of the test.
//
// Because Chdir affects the whole process, it cannot be used
// in parallel tests or tests with parallel ancestors.
func (c *common) Chdir(dir string) {
// Note: function copied from the Go 1.24.0 source tree.
oldwd, err := os.Open(".")
if err != nil {
c.Fatal(err)
}
if err := os.Chdir(dir); err != nil {
c.Fatal(err)
}
// On POSIX platforms, PWD represents “an absolute pathname of the
// current working directory.” Since we are changing the working
// directory, we should also set or update PWD to reflect that.
switch runtime.GOOS {
case "windows", "plan9":
// Windows and Plan 9 do not use the PWD variable.
default:
if !filepath.IsAbs(dir) {
dir, err = os.Getwd()
if err != nil {
c.Fatal(err)
}
}
c.Setenv("PWD", dir)
}
c.Cleanup(func() {
err := oldwd.Chdir()
oldwd.Close()
if err != nil {
// It's not safe to continue with tests if we can't
// get back to the original working directory. Since
// we are holding a dirfd, this is highly unlikely.
panic("testing.Chdir: " + err.Error())
}
})
}
// runCleanup is called at the end of the test.
func (c *common) runCleanup() {
for {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"inherits": ["rp2040"],
"build-tags": ["elecrow_rp2040"],
"build-tags": ["elecrow_rp2040", "comboat_fw"],
"serial-port": ["2e8a:000a"],
"default-stack-size": 8192,
"ldflags": [
+1 -1
View File
@@ -1,6 +1,6 @@
{
"inherits": ["rp2350"],
"build-tags": ["elecrow_rp2350"],
"build-tags": ["elecrow_rp2350", "comboat_fw"],
"serial-port": ["2e8a:000f"],
"default-stack-size": 8192,
"ldflags": [
+3
View File
@@ -0,0 +1,3 @@
{
"inherits": ["hw-651", "nrf51-s110v8"]
}
+7
View File
@@ -0,0 +1,7 @@
{
"inherits": ["nrf51"],
"build-tags": ["hw_651"],
"serial": "uart",
"flash-method": "openocd",
"openocd-interface": "cmsis-dap"
}
+4
View File
@@ -0,0 +1,4 @@
{
"inherits": ["rp2350b"],
"build-tags": ["pga2350"]
}
+11
View File
@@ -0,0 +1,11 @@
{
"inherits": [
"rp2350b"
],
"build-tags": ["pico_plus2"],
"ldflags": [
"--defsym=__flash_size=16M"
],
"serial-port": ["2e8a:000F"],
"default-stack-size": 8192
}
+4
View File
@@ -0,0 +1,4 @@
{
"inherits": ["pico2"],
"build-tags": ["pico2-w", "cyw43439"]
}
+2 -1
View File
@@ -3,5 +3,6 @@
"rp2350"
],
"build-tags": ["pico2"],
"serial-port": ["2e8a:000A"]
"serial-port": ["2e8a:000A"],
"default-stack-size": 8192
}
+1 -1
View File
@@ -4,5 +4,5 @@
"build-tags": ["virt", "qemu"],
"default-stack-size": 4096,
"linkerscript": "targets/riscv-qemu.ld",
"emulator": "qemu-system-riscv32 -machine virt -nographic -bios none -kernel {}"
"emulator": "qemu-system-riscv32 -machine virt -nographic -bios none -device virtio-rng-device -kernel {}"
}
+5 -5
View File
@@ -1,16 +1,16 @@
/* Memory map:
* https://github.com/qemu/qemu/blob/master/hw/riscv/virt.c
* RAM and flash are set to 1MB each. That should be enough for the foreseeable
* future. QEMU does not seem to limit the flash/RAM size and in fact doesn't
* seem to differentiate between it.
* Looks like we can use any address starting from 0x80000000 (so 2GB of space).
* However, using a large space slows down tests.
*/
MEMORY
{
FLASH_TEXT (rw) : ORIGIN = 0x80000000, LENGTH = 0x100000
RAM (xrw) : ORIGIN = 0x80100000, LENGTH = 0x100000
RAM (rwx) : ORIGIN = 0x80000000, LENGTH = 100M
}
REGION_ALIAS("FLASH_TEXT", RAM)
_stack_size = 2K;
INCLUDE "targets/riscv.ld"
+5
View File
@@ -0,0 +1,5 @@
{
"inherits": ["rp2350"],
"build-tags": ["rp2350b"],
"serial-port": ["2e8a:000f"]
}
+1 -1
View File
@@ -7,7 +7,7 @@
],
"linkerscript": "targets/tkey.ld",
"scheduler": "none",
"gc": "leaking",
"gc": "conservative",
"flash-command": "tkey-runapp {bin}",
"serial": "uart"
}
+15 -3
View File
@@ -303,13 +303,25 @@
// func finalizeRef(v ref)
"syscall/js.finalizeRef": (v_ref) => {
// Note: TinyGo does not support finalizers so this should never be
// called.
console.error('syscall/js.finalizeRef not implemented');
// Note: TinyGo does not support finalizers so this is only called
// for one specific case, by js.go:jsString. and can/might leak memory.
const id = v_ref & 0xffffffffn;
if (this._goRefCounts?.[id] !== undefined) {
this._goRefCounts[id]--;
if (this._goRefCounts[id] === 0) {
const v = this._values[id];
this._values[id] = null;
this._ids.delete(v);
this._idPool.push(id);
}
} else {
console.error("syscall/js.finalizeRef: unknown id", id);
}
},
// func stringVal(value string) ref
"syscall/js.stringVal": (value_ptr, value_len) => {
value_ptr >>>= 0;
const s = loadString(value_ptr, value_len);
return boxValue(s);
},
+9 -1
View File
@@ -33,8 +33,16 @@ func runargs(t *testing.T, args ...string) error {
}
func chromectx(t *testing.T) context.Context {
// see https://chromium.googlesource.com/chromium/src/+/main/docs/security/apparmor-userns-restrictions.md
opts := append(chromedp.DefaultExecAllocatorOptions[:],
chromedp.NoSandbox,
)
allocCtx, cancel := chromedp.NewExecAllocator(context.Background(), opts...)
t.Cleanup(cancel)
// looks for locally installed Chrome
ctx, ccancel := chromedp.NewContext(context.Background(), chromedp.WithErrorf(t.Errorf), chromedp.WithDebugf(t.Logf), chromedp.WithLogf(t.Logf))
ctx, ccancel := chromedp.NewContext(allocCtx, chromedp.WithErrorf(t.Errorf), chromedp.WithDebugf(t.Logf), chromedp.WithLogf(t.Logf))
t.Cleanup(ccancel)
// Wait for browser to be ready.