mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-18 03:24:00 +00:00
Merge branch 'dev' into feature/usb-common
This commit is contained in:
@@ -0,0 +1,45 @@
|
|||||||
|
name: CI for tinygo-dev docker container
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ dev ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
push_to_registry:
|
||||||
|
name: Push Docker image to GHCR/Docker Hub
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
packages: write
|
||||||
|
contents: read
|
||||||
|
steps:
|
||||||
|
- name: Check out the repo
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
- name: Docker meta
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v3
|
||||||
|
with:
|
||||||
|
images: |
|
||||||
|
tinygo/tinygo-dev
|
||||||
|
ghcr.io/${{ github.repository }}/tinygo-dev
|
||||||
|
tags: |
|
||||||
|
type=sha,format=long
|
||||||
|
type=raw,value=latest
|
||||||
|
- name: Log in to Docker Hub
|
||||||
|
uses: docker/login-action@v1
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
|
||||||
|
- name: Log in to Github Container Registry
|
||||||
|
uses: docker/login-action@v1
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
- name: Build and push
|
||||||
|
uses: docker/build-push-action@v2
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: true
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
@@ -16,6 +16,8 @@ src/device/stm32/*.go
|
|||||||
src/device/stm32/*.s
|
src/device/stm32/*.s
|
||||||
src/device/kendryte/*.go
|
src/device/kendryte/*.go
|
||||||
src/device/kendryte/*.s
|
src/device/kendryte/*.s
|
||||||
|
src/device/rp/*.go
|
||||||
|
src/device/rp/*.s
|
||||||
vendor
|
vendor
|
||||||
llvm-build
|
llvm-build
|
||||||
llvm-project
|
llvm-project
|
||||||
|
|||||||
@@ -1,3 +1,69 @@
|
|||||||
|
0.19.0
|
||||||
|
---
|
||||||
|
|
||||||
|
* **command line**
|
||||||
|
- don't consider compile-only tests as failing
|
||||||
|
- add -test flag for `tinygo list`
|
||||||
|
- escape commands while printing them with the -x flag
|
||||||
|
- make flash-command portable and safer to use
|
||||||
|
- use `extended-remote` instead of `remote` in GDB
|
||||||
|
- detect specific serial port IDs based on USB vid/pid
|
||||||
|
- add a flag to the command line to select the serial implementation
|
||||||
|
* **compiler**
|
||||||
|
- `cgo`: improve constant parser
|
||||||
|
- `compiler`: support chained interrupt handlers
|
||||||
|
- `compiler`: add support for running a builtin in a goroutine
|
||||||
|
- `compiler`: do not emit nil checks for loading closure variables
|
||||||
|
- `compiler`: skip context parameter when starting regular goroutine
|
||||||
|
- `compiler`: refactor method names
|
||||||
|
- `compiler`: add function and global section pragmas
|
||||||
|
- `compiler`: implement `syscall.rawSyscallNoError` in inline assembly
|
||||||
|
- `interp`: ignore inline assembly in markExternal
|
||||||
|
- `interp`: fix a bug in pointer cast workaround
|
||||||
|
- `loader`: fix testing a main package
|
||||||
|
* **standard library**
|
||||||
|
- `crypto/rand`: replace this package with a TinyGo version
|
||||||
|
- `machine`: make USBCDC global a pointer
|
||||||
|
- `machine`: make UART objects pointer receivers
|
||||||
|
- `machine`: define Serial as the default output
|
||||||
|
- `net`: add initial support for net.IP
|
||||||
|
- `net`: add more net compatibility
|
||||||
|
- `os`: add stub for os.ReadDir
|
||||||
|
- `os`: add FileMode constants from Go 1.16
|
||||||
|
- `os`: add stubs required for net/http
|
||||||
|
- `os`: implement process related functions
|
||||||
|
- `reflect`: implement AppendSlice
|
||||||
|
- `reflect`: add stubs required for net/http
|
||||||
|
- `runtime`: make task.Data a 64-bit integer to avoid overflow
|
||||||
|
- `runtime`: expose memory stats
|
||||||
|
- `sync`: implement NewCond
|
||||||
|
- `syscall`: fix int type in libc version
|
||||||
|
* **targets**
|
||||||
|
- `cortexm`: do not disable interrupts on abort
|
||||||
|
- `cortexm`: bump default stack size to 2048 bytes
|
||||||
|
- `nrf`: avoid heap allocation in waitForEvent
|
||||||
|
- `nrf`: don't trigger a heap allocation in SPI.Transfer
|
||||||
|
- `nrf52840`: add support for flashing with the BOSSA tool
|
||||||
|
- `rp2040`: add support for GPIO input
|
||||||
|
- `rp2040`: add basic support for ADC
|
||||||
|
- `rp2040`: gpio and adc pin definitions
|
||||||
|
- `rp2040`: implement UART
|
||||||
|
- `rp2040`: patch elf to checksum 2nd stage boot
|
||||||
|
- `stm32`: add PWM for most chips
|
||||||
|
- `stm32`: add support for pin interrupts
|
||||||
|
- `stm32f103`: add support for PinInputPullup / PinInputPulldown
|
||||||
|
- `wasi`: remove wasm build tag
|
||||||
|
* **boards**
|
||||||
|
- `feather-rp2040`: add support for this board
|
||||||
|
- `feather-nrf52840-sense`: add board definition for this board
|
||||||
|
- `pca10059`: support flashing from Windows
|
||||||
|
- `nano-rp2040`: add this board
|
||||||
|
- `nano-33-ble`: add support for this board
|
||||||
|
- `pico`: add the Raspberry Pi Pico board with the new RP2040 chip
|
||||||
|
- `qtpy`: add pin for neopixels
|
||||||
|
- all: add definition for ws2812 for supported boards
|
||||||
|
|
||||||
|
|
||||||
0.18.0
|
0.18.0
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -230,6 +230,8 @@ smoketest:
|
|||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=pca10040 examples/mcp3008
|
$(TINYGO) build -size short -o test.hex -target=pca10040 examples/mcp3008
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
|
$(TINYGO) build -size short -o test.hex -target=pca10040 examples/memstats
|
||||||
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=microbit examples/microbit-blink
|
$(TINYGO) build -size short -o test.hex -target=microbit examples/microbit-blink
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=pca10040 examples/pininterrupt
|
$(TINYGO) build -size short -o test.hex -target=pca10040 examples/pininterrupt
|
||||||
@@ -334,9 +336,11 @@ smoketest:
|
|||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=feather-nrf52840 examples/blinky1
|
$(TINYGO) build -size short -o test.hex -target=feather-nrf52840 examples/blinky1
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
|
$(TINYGO) build -size short -o test.hex -target=feather-nrf52840-sense examples/blinky1
|
||||||
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=itsybitsy-nrf52840 examples/blinky1
|
$(TINYGO) build -size short -o test.hex -target=itsybitsy-nrf52840 examples/blinky1
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=qtpy examples/blinky1
|
$(TINYGO) build -size short -o test.hex -target=qtpy examples/serial
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=teensy40 examples/blinky1
|
$(TINYGO) build -size short -o test.hex -target=teensy40 examples/blinky1
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
@@ -354,7 +358,13 @@ smoketest:
|
|||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=arduino-nano33 examples/blinky1
|
$(TINYGO) build -size short -o test.hex -target=arduino-nano33 examples/blinky1
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=pico examples/blinky1
|
$(TINYGO) build -size short -o test.hex -target=pico examples/blinky1
|
||||||
|
@$(MD5SUM) test.hex
|
||||||
|
$(TINYGO) build -size short -o test.hex -target=nano-33-ble examples/blinky1
|
||||||
|
@$(MD5SUM) test.hex
|
||||||
|
$(TINYGO) build -size short -o test.hex -target=nano-rp2040 examples/blinky1
|
||||||
|
@$(MD5SUM) test.hex
|
||||||
|
$(TINYGO) build -size short -o test.hex -target=feather-rp2040 examples/blinky1
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
# test pwm
|
# test pwm
|
||||||
$(TINYGO) build -size short -o test.hex -target=itsybitsy-m0 examples/pwm
|
$(TINYGO) build -size short -o test.hex -target=itsybitsy-m0 examples/pwm
|
||||||
@@ -428,6 +438,8 @@ endif
|
|||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=pca10040 -opt=1 examples/blinky1
|
$(TINYGO) build -size short -o test.hex -target=pca10040 -opt=1 examples/blinky1
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
|
$(TINYGO) build -size short -o test.hex -target=pca10040 -serial=none examples/echo
|
||||||
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -o test.nro -target=nintendoswitch examples/serial
|
$(TINYGO) build -o test.nro -target=nintendoswitch examples/serial
|
||||||
@$(MD5SUM) test.nro
|
@$(MD5SUM) test.nro
|
||||||
$(TINYGO) build -size short -o test.hex -target=pca10040 -opt=0 ./testdata/stdlib.go
|
$(TINYGO) build -size short -o test.hex -target=pca10040 -opt=0 ./testdata/stdlib.go
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ See the [getting started instructions](https://tinygo.org/getting-started/) for
|
|||||||
|
|
||||||
You can compile TinyGo programs for microcontrollers, WebAssembly and Linux.
|
You can compile TinyGo programs for microcontrollers, WebAssembly and Linux.
|
||||||
|
|
||||||
The following 62 microcontroller boards are currently supported:
|
The following 68 microcontroller boards are currently supported:
|
||||||
|
|
||||||
* [Adafruit Circuit Playground Bluefruit](https://www.adafruit.com/product/4333)
|
* [Adafruit Circuit Playground Bluefruit](https://www.adafruit.com/product/4333)
|
||||||
* [Adafruit Circuit Playground Express](https://www.adafruit.com/product/3333)
|
* [Adafruit Circuit Playground Express](https://www.adafruit.com/product/3333)
|
||||||
@@ -52,6 +52,8 @@ The following 62 microcontroller boards are currently supported:
|
|||||||
* [Adafruit Feather M4](https://www.adafruit.com/product/3857)
|
* [Adafruit Feather M4](https://www.adafruit.com/product/3857)
|
||||||
* [Adafruit Feather M4 CAN](https://www.adafruit.com/product/4759)
|
* [Adafruit Feather M4 CAN](https://www.adafruit.com/product/4759)
|
||||||
* [Adafruit Feather nRF52840 Express](https://www.adafruit.com/product/4062)
|
* [Adafruit Feather nRF52840 Express](https://www.adafruit.com/product/4062)
|
||||||
|
* [Adafruit Feather nRF52840 Sense](https://www.adafruit.com/product/4516)
|
||||||
|
* [Adafruit Feather RP2040](https://www.adafruit.com/product/4884)
|
||||||
* [Adafruit Feather STM32F405 Express](https://www.adafruit.com/product/4382)
|
* [Adafruit Feather STM32F405 Express](https://www.adafruit.com/product/4382)
|
||||||
* [Adafruit Grand Central M4](https://www.adafruit.com/product/4064)
|
* [Adafruit Grand Central M4](https://www.adafruit.com/product/4064)
|
||||||
* [Adafruit ItsyBitsy M0](https://www.adafruit.com/product/3727)
|
* [Adafruit ItsyBitsy M0](https://www.adafruit.com/product/3727)
|
||||||
@@ -68,7 +70,10 @@ The following 62 microcontroller boards are currently supported:
|
|||||||
* [Arduino Mega 2560](https://store.arduino.cc/arduino-mega-2560-rev3)
|
* [Arduino Mega 2560](https://store.arduino.cc/arduino-mega-2560-rev3)
|
||||||
* [Arduino MKR1000](https://store.arduino.cc/arduino-mkr1000-wifi)
|
* [Arduino MKR1000](https://store.arduino.cc/arduino-mkr1000-wifi)
|
||||||
* [Arduino Nano](https://store.arduino.cc/arduino-nano)
|
* [Arduino Nano](https://store.arduino.cc/arduino-nano)
|
||||||
* [Arduino Nano33 IoT](https://store.arduino.cc/nano-33-iot)
|
* [Arduino Nano 33 BLE](https://store.arduino.cc/nano-33-ble)
|
||||||
|
* [Arduino Nano 33 BLE Sense](https://store.arduino.cc/nano-33-ble-sense)
|
||||||
|
* [Arduino Nano 33 IoT](https://store.arduino.cc/nano-33-iot)
|
||||||
|
* [Arduino Nano RP2040 Connect](https://store.arduino.cc/nano-rp2040-connect)
|
||||||
* [Arduino Uno](https://store.arduino.cc/arduino-uno-rev3)
|
* [Arduino Uno](https://store.arduino.cc/arduino-uno-rev3)
|
||||||
* [Arduino Zero](https://store.arduino.cc/usa/arduino-zero)
|
* [Arduino Zero](https://store.arduino.cc/usa/arduino-zero)
|
||||||
* [BBC micro:bit](https://microbit.org/)
|
* [BBC micro:bit](https://microbit.org/)
|
||||||
@@ -95,6 +100,7 @@ The following 62 microcontroller boards are currently supported:
|
|||||||
* [PJRC Teensy 3.6](https://www.pjrc.com/store/teensy36.html)
|
* [PJRC Teensy 3.6](https://www.pjrc.com/store/teensy36.html)
|
||||||
* [PJRC Teensy 4.0](https://www.pjrc.com/store/teensy40.html)
|
* [PJRC Teensy 4.0](https://www.pjrc.com/store/teensy40.html)
|
||||||
* [ProductivityOpen P1AM-100](https://facts-engineering.github.io/modules/P1AM-100/P1AM-100.html)
|
* [ProductivityOpen P1AM-100](https://facts-engineering.github.io/modules/P1AM-100/P1AM-100.html)
|
||||||
|
* [Raspberry Pi Pico](https://www.raspberrypi.org/products/raspberry-pi-pico/)
|
||||||
* [Seeed Wio Terminal](https://www.seeedstudio.com/Wio-Terminal-p-4509.html)
|
* [Seeed Wio Terminal](https://www.seeedstudio.com/Wio-Terminal-p-4509.html)
|
||||||
* [Seeed Seeeduino XIAO](https://www.seeedstudio.com/Seeeduino-XIAO-Arduino-Microcontroller-SAMD21-Cortex-M0+-p-4426.html)
|
* [Seeed Seeeduino XIAO](https://www.seeedstudio.com/Seeeduino-XIAO-Arduino-Microcontroller-SAMD21-Cortex-M0+-p-4426.html)
|
||||||
* [Seeed Sipeed MAix BiT](https://www.seeedstudio.com/Sipeed-MAix-BiT-for-RISC-V-AI-IoT-p-2872.html)
|
* [Seeed Sipeed MAix BiT](https://www.seeedstudio.com/Sipeed-MAix-BiT-for-RISC-V-AI-IoT-p-2872.html)
|
||||||
|
|||||||
+144
-65
@@ -12,7 +12,9 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/types"
|
"go/types"
|
||||||
|
"hash/crc32"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"math/bits"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
@@ -98,7 +100,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
|||||||
AutomaticStackSize: config.AutomaticStackSize(),
|
AutomaticStackSize: config.AutomaticStackSize(),
|
||||||
DefaultStackSize: config.Target.DefaultStackSize,
|
DefaultStackSize: config.Target.DefaultStackSize,
|
||||||
NeedsStackObjects: config.NeedsStackObjects(),
|
NeedsStackObjects: config.NeedsStackObjects(),
|
||||||
Debug: config.Debug(),
|
Debug: true,
|
||||||
LLVMFeatures: config.LLVMFeatures(),
|
LLVMFeatures: config.LLVMFeatures(),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -468,33 +470,10 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
|||||||
linkerDependencies = append(linkerDependencies, job)
|
linkerDependencies = append(linkerDependencies, job)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add libc dependency if needed.
|
|
||||||
root := goenv.Get("TINYGOROOT")
|
|
||||||
switch config.Target.Libc {
|
|
||||||
case "picolibc":
|
|
||||||
job, err := Picolibc.load(config.Triple(), config.CPU(), dir)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// The library needs to be compiled (cache miss).
|
|
||||||
jobs = append(jobs, job.dependencies...)
|
|
||||||
jobs = append(jobs, job)
|
|
||||||
linkerDependencies = append(linkerDependencies, job)
|
|
||||||
case "wasi-libc":
|
|
||||||
path := filepath.Join(root, "lib/wasi-libc/sysroot/lib/wasm32-wasi/libc.a")
|
|
||||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
|
||||||
return errors.New("could not find wasi-libc, perhaps you need to run `make wasi-libc`?")
|
|
||||||
}
|
|
||||||
ldflags = append(ldflags, path)
|
|
||||||
case "":
|
|
||||||
// no library specified, so nothing to do
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("unknown libc: %s", config.Target.Libc)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add jobs to compile extra files. These files are in C or assembly and
|
// Add jobs to compile extra files. These files are in C or assembly and
|
||||||
// contain things like the interrupt vector table and low level operations
|
// contain things like the interrupt vector table and low level operations
|
||||||
// such as stack switching.
|
// such as stack switching.
|
||||||
|
root := goenv.Get("TINYGOROOT")
|
||||||
for _, path := range config.ExtraFiles() {
|
for _, path := range config.ExtraFiles() {
|
||||||
abspath := filepath.Join(root, path)
|
abspath := filepath.Join(root, path)
|
||||||
job := &compileJob{
|
job := &compileJob{
|
||||||
@@ -535,6 +514,64 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
|||||||
ldflags = append(ldflags, lprogram.LDFlags...)
|
ldflags = append(ldflags, lprogram.LDFlags...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add libc dependency if needed.
|
||||||
|
switch config.Target.Libc {
|
||||||
|
case "picolibc":
|
||||||
|
job, err := Picolibc.load(config.Triple(), config.CPU(), dir)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// The library needs to be compiled (cache miss).
|
||||||
|
jobs = append(jobs, job.dependencies...)
|
||||||
|
jobs = append(jobs, job)
|
||||||
|
linkerDependencies = append(linkerDependencies, job)
|
||||||
|
case "wasi-libc":
|
||||||
|
path := filepath.Join(root, "lib/wasi-libc/sysroot/lib/wasm32-wasi/libc.a")
|
||||||
|
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||||
|
return errors.New("could not find wasi-libc, perhaps you need to run `make wasi-libc`?")
|
||||||
|
}
|
||||||
|
job := dummyCompileJob(path)
|
||||||
|
jobs = append(jobs, job)
|
||||||
|
linkerDependencies = append(linkerDependencies, job)
|
||||||
|
case "":
|
||||||
|
// no library specified, so nothing to do
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unknown libc: %s", config.Target.Libc)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Strip debug information with -no-debug.
|
||||||
|
if !config.Debug() {
|
||||||
|
for _, tag := range config.BuildTags() {
|
||||||
|
if tag == "baremetal" {
|
||||||
|
// Don't use -no-debug on baremetal targets. It makes no sense:
|
||||||
|
// the debug information isn't flashed to the device anyway.
|
||||||
|
return fmt.Errorf("stripping debug information is unnecessary for baremetal targets")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if config.Target.Linker == "wasm-ld" {
|
||||||
|
// Don't just strip debug information, also compress relocations
|
||||||
|
// while we're at it. Relocations can only be compressed when debug
|
||||||
|
// information is stripped.
|
||||||
|
ldflags = append(ldflags, "--strip-debug", "--compress-relocations")
|
||||||
|
} else {
|
||||||
|
switch config.GOOS() {
|
||||||
|
case "linux":
|
||||||
|
// Either real linux or an embedded system (like AVR) that
|
||||||
|
// pretends to be Linux. It's a ELF linker wrapped by GCC in any
|
||||||
|
// case.
|
||||||
|
ldflags = append(ldflags, "-Wl,--strip-debug")
|
||||||
|
case "darwin":
|
||||||
|
// MacOS (darwin) doesn't have a linker flag to strip debug
|
||||||
|
// information. Apple expects you to use the strip command
|
||||||
|
// instead.
|
||||||
|
return errors.New("cannot remove debug information: MacOS doesn't suppor this linker flag")
|
||||||
|
default:
|
||||||
|
// Other OSes may have different flags.
|
||||||
|
return errors.New("cannot remove debug information: unknown OS: " + config.GOOS())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Create a linker job, which links all object files together and does some
|
// Create a linker job, which links all object files together and does some
|
||||||
// extra stuff that can only be done after linking.
|
// extra stuff that can only be done after linking.
|
||||||
jobs = append(jobs, &compileJob{
|
jobs = append(jobs, &compileJob{
|
||||||
@@ -547,8 +584,8 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
|||||||
}
|
}
|
||||||
ldflags = append(ldflags, dependency.result)
|
ldflags = append(ldflags, dependency.result)
|
||||||
}
|
}
|
||||||
if config.Options.PrintCommands {
|
if config.Options.PrintCommands != nil {
|
||||||
fmt.Printf("%s %s\n", config.Target.Linker, strings.Join(ldflags, " "))
|
config.Options.PrintCommands(config.Target.Linker, ldflags...)
|
||||||
}
|
}
|
||||||
err = link(config.Target.Linker, ldflags...)
|
err = link(config.Target.Linker, ldflags...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -566,6 +603,8 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply ELF patches
|
||||||
if config.AutomaticStackSize() {
|
if config.AutomaticStackSize() {
|
||||||
// Modify the .tinygo_stacksizes section that contains a stack size
|
// Modify the .tinygo_stacksizes section that contains a stack size
|
||||||
// for each goroutine.
|
// for each goroutine.
|
||||||
@@ -574,6 +613,13 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
|||||||
return fmt.Errorf("could not modify stack sizes: %w", err)
|
return fmt.Errorf("could not modify stack sizes: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if config.RP2040BootPatch() {
|
||||||
|
// Patch the second stage bootloader CRC into the .boot2 section
|
||||||
|
err = patchRP2040BootCRC(executable)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not patch RP2040 second stage boot loader: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if config.Options.PrintSizes == "short" || config.Options.PrintSizes == "full" {
|
if config.Options.PrintSizes == "short" || config.Options.PrintSizes == "full" {
|
||||||
sizes, err := loadProgramSize(executable)
|
sizes, err := loadProgramSize(executable)
|
||||||
@@ -639,6 +685,18 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
case "nrf-dfu":
|
||||||
|
// special format for nrfutil for Nordic chips
|
||||||
|
tmphexpath := filepath.Join(dir, "main.hex")
|
||||||
|
err := objcopy(executable, tmphexpath, "hex")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
tmppath = filepath.Join(dir, "main"+outext)
|
||||||
|
err = makeDFUFirmwareImage(config.Options, tmphexpath, tmppath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unknown output binary format: %s", outputBinaryFormat)
|
return fmt.Errorf("unknown output binary format: %s", outputBinaryFormat)
|
||||||
}
|
}
|
||||||
@@ -908,30 +966,7 @@ func determineStackSizes(mod llvm.Module, executable string) ([]string, map[stri
|
|||||||
// stack size information. Before this modification, all stack sizes in the
|
// stack size information. Before this modification, all stack sizes in the
|
||||||
// section assume the default stack size (which is relatively big).
|
// section assume the default stack size (which is relatively big).
|
||||||
func modifyStackSizes(executable string, stackSizeLoads []string, stackSizes map[string]functionStackSize) error {
|
func modifyStackSizes(executable string, stackSizeLoads []string, stackSizes map[string]functionStackSize) error {
|
||||||
fp, err := os.OpenFile(executable, os.O_RDWR, 0)
|
data, fileHeader, err := getElfSectionData(executable, ".tinygo_stacksizes")
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer fp.Close()
|
|
||||||
|
|
||||||
elfFile, err := elf.NewFile(fp)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
section := elfFile.Section(".tinygo_stacksizes")
|
|
||||||
if section == nil {
|
|
||||||
return errors.New("could not find .tinygo_stacksizes section")
|
|
||||||
}
|
|
||||||
|
|
||||||
if section.Size != section.FileSize {
|
|
||||||
// Sanity check.
|
|
||||||
return fmt.Errorf("expected .tinygo_stacksizes to have identical size and file size, got %d and %d", section.Size, section.FileSize)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read all goroutine stack sizes.
|
|
||||||
data := make([]byte, section.Size)
|
|
||||||
_, err = fp.ReadAt(data, int64(section.Offset))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -953,15 +988,19 @@ func modifyStackSizes(executable string, stackSizeLoads []string, stackSizes map
|
|||||||
if fn.stackSizeType == stacksize.Bounded {
|
if fn.stackSizeType == stacksize.Bounded {
|
||||||
stackSize := uint32(fn.stackSize)
|
stackSize := uint32(fn.stackSize)
|
||||||
|
|
||||||
// Adding 4 for the stack canary. Even though the size may be
|
|
||||||
// automatically determined, stack overflow checking is still
|
|
||||||
// important as the stack size cannot be determined for all
|
|
||||||
// goroutines.
|
|
||||||
stackSize += 4
|
|
||||||
|
|
||||||
// Add stack size used by interrupts.
|
// Add stack size used by interrupts.
|
||||||
switch elfFile.Machine {
|
switch fileHeader.Machine {
|
||||||
case elf.EM_ARM:
|
case elf.EM_ARM:
|
||||||
|
if stackSize%8 != 0 {
|
||||||
|
// If the stack isn't a multiple of 8, it means the leaf
|
||||||
|
// function with the biggest stack depth doesn't have an aligned
|
||||||
|
// stack. If the STKALIGN flag is set (which it is by default)
|
||||||
|
// the interrupt controller will forcibly align the stack before
|
||||||
|
// storing in-use registers. This will thus overwrite one word
|
||||||
|
// past the end of the stack (off-by-one).
|
||||||
|
stackSize += 4
|
||||||
|
}
|
||||||
|
|
||||||
// On Cortex-M (assumed here), this stack size is 8 words or 32
|
// On Cortex-M (assumed here), this stack size is 8 words or 32
|
||||||
// bytes. This is only to store the registers that the interrupt
|
// bytes. This is only to store the registers that the interrupt
|
||||||
// may modify, the interrupt will switch to the interrupt stack
|
// may modify, the interrupt will switch to the interrupt stack
|
||||||
@@ -969,6 +1008,14 @@ func modifyStackSizes(executable string, stackSizeLoads []string, stackSizes map
|
|||||||
// Some background:
|
// Some background:
|
||||||
// https://interrupt.memfault.com/blog/cortex-m-rtos-context-switching
|
// https://interrupt.memfault.com/blog/cortex-m-rtos-context-switching
|
||||||
stackSize += 32
|
stackSize += 32
|
||||||
|
|
||||||
|
// Adding 4 for the stack canary, and another 4 to keep the
|
||||||
|
// stack aligned. Even though the size may be automatically
|
||||||
|
// determined, stack overflow checking is still important as the
|
||||||
|
// stack size cannot be determined for all goroutines.
|
||||||
|
stackSize += 8
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unknown architecture: %s", fileHeader.Machine.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally write the stack size to the binary.
|
// Finally write the stack size to the binary.
|
||||||
@@ -976,13 +1023,7 @@ func modifyStackSizes(executable string, stackSizeLoads []string, stackSizes map
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write back the modified stack sizes.
|
return replaceElfSection(executable, ".tinygo_stacksizes", data)
|
||||||
_, err = fp.WriteAt(data, int64(section.Offset))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// printStacks prints the maximum stack depth for functions that are started as
|
// printStacks prints the maximum stack depth for functions that are started as
|
||||||
@@ -1014,3 +1055,41 @@ func printStacks(calculatedStacks []string, stackSizes map[string]functionStackS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RP2040 second stage bootloader CRC32 calculation
|
||||||
|
//
|
||||||
|
// Spec: https://datasheets.raspberrypi.org/rp2040/rp2040-datasheet.pdf
|
||||||
|
// Section: 2.8.1.3.1. Checksum
|
||||||
|
func patchRP2040BootCRC(executable string) error {
|
||||||
|
bytes, _, err := getElfSectionData(executable, ".boot2")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(bytes) != 256 {
|
||||||
|
return fmt.Errorf("rp2040 .boot2 section must be exactly 256 bytes")
|
||||||
|
}
|
||||||
|
|
||||||
|
// From the 'official' RP2040 checksum script:
|
||||||
|
//
|
||||||
|
// Our bootrom CRC32 is slightly bass-ackward but it's
|
||||||
|
// best to work around for now (FIXME)
|
||||||
|
// 100% worth it to save two Thumb instructions
|
||||||
|
revBytes := make([]byte, len(bytes))
|
||||||
|
for i := range bytes {
|
||||||
|
revBytes[i] = bits.Reverse8(bytes[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
// crc32.Update does an initial negate and negates the
|
||||||
|
// result, so to meet RP2040 spec, pass 0x0 as initial
|
||||||
|
// hash and negate returned value.
|
||||||
|
//
|
||||||
|
// Note: checksum is over 252 bytes (256 - 4)
|
||||||
|
hash := bits.Reverse32(crc32.Update(0x0, crc32.IEEETable, revBytes[:252]) ^ 0xFFFFFFFF)
|
||||||
|
|
||||||
|
// Write the CRC to the end of the bootloader.
|
||||||
|
binary.LittleEndian.PutUint32(bytes[252:], hash)
|
||||||
|
|
||||||
|
// Update the .boot2 section to included the CRC
|
||||||
|
return replaceElfSection(executable, ".boot2", bytes)
|
||||||
|
}
|
||||||
|
|||||||
+3
-3
@@ -56,7 +56,7 @@ import (
|
|||||||
// depfile but without invalidating its name. For this reason, the depfile is
|
// depfile but without invalidating its name. For this reason, the depfile is
|
||||||
// written on each new compilation (even when it seems unnecessary). However, it
|
// written on each new compilation (even when it seems unnecessary). However, it
|
||||||
// could in rare cases lead to a stale file fetched from the cache.
|
// could in rare cases lead to a stale file fetched from the cache.
|
||||||
func compileAndCacheCFile(abspath, tmpdir string, cflags []string, printCommands bool) (string, error) {
|
func compileAndCacheCFile(abspath, tmpdir string, cflags []string, printCommands func(string, ...string)) (string, error) {
|
||||||
// Hash input file.
|
// Hash input file.
|
||||||
fileHash, err := hashFile(abspath)
|
fileHash, err := hashFile(abspath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -128,8 +128,8 @@ func compileAndCacheCFile(abspath, tmpdir string, cflags []string, printCommands
|
|||||||
// flags (for the assembler) is a compiler error.
|
// flags (for the assembler) is a compiler error.
|
||||||
flags = append(flags, "-Qunused-arguments")
|
flags = append(flags, "-Qunused-arguments")
|
||||||
}
|
}
|
||||||
if printCommands {
|
if printCommands != nil {
|
||||||
fmt.Printf("clang %s\n", strings.Join(flags, " "))
|
printCommands("clang", flags...)
|
||||||
}
|
}
|
||||||
err = runCCompiler(flags...)
|
err = runCCompiler(flags...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
package builder
|
||||||
|
|
||||||
|
import (
|
||||||
|
"debug/elf"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getElfSectionData(executable string, sectionName string) ([]byte, elf.FileHeader, error) {
|
||||||
|
elfFile, err := elf.Open(executable)
|
||||||
|
if err != nil {
|
||||||
|
return nil, elf.FileHeader{}, err
|
||||||
|
}
|
||||||
|
defer elfFile.Close()
|
||||||
|
|
||||||
|
section := elfFile.Section(sectionName)
|
||||||
|
if section == nil {
|
||||||
|
return nil, elf.FileHeader{}, fmt.Errorf("could not find %s section", sectionName)
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := section.Data()
|
||||||
|
|
||||||
|
return data, elfFile.FileHeader, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func replaceElfSection(executable string, sectionName string, data []byte) error {
|
||||||
|
fp, err := os.OpenFile(executable, os.O_RDWR, 0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer fp.Close()
|
||||||
|
|
||||||
|
elfFile, err := elf.Open(executable)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer elfFile.Close()
|
||||||
|
|
||||||
|
section := elfFile.Section(sectionName)
|
||||||
|
if section == nil {
|
||||||
|
return fmt.Errorf("could not find %s section", sectionName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implicitly check for compressed sections
|
||||||
|
if section.Size != section.FileSize {
|
||||||
|
return fmt.Errorf("expected section %s to have identical size and file size, got %d and %d", sectionName, section.Size, section.FileSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only permit complete replacement of section
|
||||||
|
if section.Size != uint64(len(data)) {
|
||||||
|
return fmt.Errorf("expected section %s to have size %d, was actually %d", sectionName, len(data), section.Size)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the replacement section data
|
||||||
|
_, err = fp.WriteAt(data, int64(section.Offset))
|
||||||
|
return err
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package builder
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os/exec"
|
||||||
|
|
||||||
|
"github.com/tinygo-org/tinygo/compileopts"
|
||||||
|
)
|
||||||
|
|
||||||
|
// https://infocenter.nordicsemi.com/index.jsp?topic=%2Fug_nrfutil%2FUG%2Fnrfutil%2Fnrfutil_intro.html
|
||||||
|
|
||||||
|
func makeDFUFirmwareImage(options *compileopts.Options, infile, outfile string) error {
|
||||||
|
cmdLine := []string{"nrfutil", "pkg", "generate", "--hw-version", "52", "--sd-req", "0x0", "--debug-mode", "--application", infile, outfile}
|
||||||
|
|
||||||
|
if options.PrintCommands != nil {
|
||||||
|
options.PrintCommands(cmdLine[0], cmdLine[1:]...)
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := exec.Command(cmdLine[0], cmdLine[1:]...)
|
||||||
|
cmd.Stdout = ioutil.Discard
|
||||||
|
err := cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not run nrfutil pkg generate: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
+33
-7
@@ -55,7 +55,7 @@ func (c *Config) GOARCH() string {
|
|||||||
|
|
||||||
// BuildTags returns the complete list of build tags used during this build.
|
// BuildTags returns the complete list of build tags used during this build.
|
||||||
func (c *Config) BuildTags() []string {
|
func (c *Config) BuildTags() []string {
|
||||||
tags := append(c.Target.BuildTags, []string{"tinygo", "gc." + c.GC(), "scheduler." + c.Scheduler()}...)
|
tags := append(c.Target.BuildTags, []string{"tinygo", "math_big_pure_go", "gc." + c.GC(), "scheduler." + c.Scheduler(), "serial." + c.Serial()}...)
|
||||||
for i := 1; i <= c.GoMinorVersion; i++ {
|
for i := 1; i <= c.GoMinorVersion; i++ {
|
||||||
tags = append(tags, fmt.Sprintf("go1.%d", i))
|
tags = append(tags, fmt.Sprintf("go1.%d", i))
|
||||||
}
|
}
|
||||||
@@ -89,7 +89,7 @@ func (c *Config) NeedsStackObjects() bool {
|
|||||||
switch c.GC() {
|
switch c.GC() {
|
||||||
case "conservative", "extalloc":
|
case "conservative", "extalloc":
|
||||||
for _, tag := range c.BuildTags() {
|
for _, tag := range c.BuildTags() {
|
||||||
if tag == "wasm" {
|
if tag == "tinygo.wasm" {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -113,6 +113,18 @@ func (c *Config) Scheduler() string {
|
|||||||
return "coroutines"
|
return "coroutines"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Serial returns the serial implementation for this build configuration: uart,
|
||||||
|
// usb (meaning USB-CDC), or none.
|
||||||
|
func (c *Config) Serial() string {
|
||||||
|
if c.Options.Serial != "" {
|
||||||
|
return c.Options.Serial
|
||||||
|
}
|
||||||
|
if c.Target.Serial != "" {
|
||||||
|
return c.Target.Serial
|
||||||
|
}
|
||||||
|
return "none"
|
||||||
|
}
|
||||||
|
|
||||||
// OptLevels returns the optimization level (0-2), size level (0-2), and inliner
|
// OptLevels returns the optimization level (0-2), size level (0-2), and inliner
|
||||||
// threshold as used in the LLVM optimization pipeline.
|
// threshold as used in the LLVM optimization pipeline.
|
||||||
func (c *Config) OptLevels() (optLevel, sizeLevel int, inlinerThreshold uint) {
|
func (c *Config) OptLevels() (optLevel, sizeLevel int, inlinerThreshold uint) {
|
||||||
@@ -176,6 +188,15 @@ func (c *Config) AutomaticStackSize() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RP2040BootPatch returns whether the RP2040 boot patch should be applied that
|
||||||
|
// calculates and patches in the checksum for the 2nd stage bootloader.
|
||||||
|
func (c *Config) RP2040BootPatch() bool {
|
||||||
|
if c.Target.RP2040BootPatch != nil {
|
||||||
|
return *c.Target.RP2040BootPatch
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// CFlags returns the flags to pass to the C compiler. This is necessary for CGo
|
// CFlags returns the flags to pass to the C compiler. This is necessary for CGo
|
||||||
// preprocessing.
|
// preprocessing.
|
||||||
func (c *Config) CFlags() []string {
|
func (c *Config) CFlags() []string {
|
||||||
@@ -188,9 +209,8 @@ func (c *Config) CFlags() []string {
|
|||||||
cflags = append(cflags, "-nostdlibinc", "-Xclang", "-internal-isystem", "-Xclang", filepath.Join(root, "lib", "picolibc", "newlib", "libc", "include"))
|
cflags = append(cflags, "-nostdlibinc", "-Xclang", "-internal-isystem", "-Xclang", filepath.Join(root, "lib", "picolibc", "newlib", "libc", "include"))
|
||||||
cflags = append(cflags, "-I"+filepath.Join(root, "lib/picolibc-include"))
|
cflags = append(cflags, "-I"+filepath.Join(root, "lib/picolibc-include"))
|
||||||
}
|
}
|
||||||
if c.Debug() {
|
// Always emit debug information. It is optionally stripped at link time.
|
||||||
cflags = append(cflags, "-g")
|
cflags = append(cflags, "-g")
|
||||||
}
|
|
||||||
return cflags
|
return cflags
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,8 +249,9 @@ func (c *Config) VerifyIR() bool {
|
|||||||
return c.Options.VerifyIR
|
return c.Options.VerifyIR
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug returns whether to add debug symbols to the IR, for debugging with GDB
|
// Debug returns whether debug (DWARF) information should be retained by the
|
||||||
// and similar.
|
// linker. By default, debug information is retained but it can be removed with
|
||||||
|
// the -no-debug flag.
|
||||||
func (c *Config) Debug() bool {
|
func (c *Config) Debug() bool {
|
||||||
return c.Options.Debug
|
return c.Options.Debug
|
||||||
}
|
}
|
||||||
@@ -254,6 +275,11 @@ func (c *Config) BinaryFormat(ext string) string {
|
|||||||
// More information:
|
// More information:
|
||||||
// https://github.com/Microsoft/uf2
|
// https://github.com/Microsoft/uf2
|
||||||
return "uf2"
|
return "uf2"
|
||||||
|
case ".zip":
|
||||||
|
if c.Target.BinaryFormat != "" {
|
||||||
|
return c.Target.BinaryFormat
|
||||||
|
}
|
||||||
|
return "zip"
|
||||||
default:
|
default:
|
||||||
// Use the ELF format for unrecognized file formats.
|
// Use the ELF format for unrecognized file formats.
|
||||||
return "elf"
|
return "elf"
|
||||||
|
|||||||
+12
-1
@@ -9,6 +9,7 @@ import (
|
|||||||
var (
|
var (
|
||||||
validGCOptions = []string{"none", "leaking", "extalloc", "conservative"}
|
validGCOptions = []string{"none", "leaking", "extalloc", "conservative"}
|
||||||
validSchedulerOptions = []string{"none", "tasks", "coroutines"}
|
validSchedulerOptions = []string{"none", "tasks", "coroutines"}
|
||||||
|
validSerialOptions = []string{"none", "uart", "usb"}
|
||||||
validPrintSizeOptions = []string{"none", "short", "full"}
|
validPrintSizeOptions = []string{"none", "short", "full"}
|
||||||
validPanicStrategyOptions = []string{"print", "trap"}
|
validPanicStrategyOptions = []string{"print", "trap"}
|
||||||
validOptOptions = []string{"none", "0", "1", "2", "s", "z"}
|
validOptOptions = []string{"none", "0", "1", "2", "s", "z"}
|
||||||
@@ -22,10 +23,11 @@ type Options struct {
|
|||||||
GC string
|
GC string
|
||||||
PanicStrategy string
|
PanicStrategy string
|
||||||
Scheduler string
|
Scheduler string
|
||||||
|
Serial string
|
||||||
PrintIR bool
|
PrintIR bool
|
||||||
DumpSSA bool
|
DumpSSA bool
|
||||||
VerifyIR bool
|
VerifyIR bool
|
||||||
PrintCommands bool
|
PrintCommands func(cmd string, args ...string)
|
||||||
Debug bool
|
Debug bool
|
||||||
PrintSizes string
|
PrintSizes string
|
||||||
PrintAllocs *regexp.Regexp // regexp string
|
PrintAllocs *regexp.Regexp // regexp string
|
||||||
@@ -59,6 +61,15 @@ func (o *Options) Verify() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if o.Serial != "" {
|
||||||
|
valid := isInArray(validSerialOptions, o.Serial)
|
||||||
|
if !valid {
|
||||||
|
return fmt.Errorf(`invalid serial option '%s': valid values are %s`,
|
||||||
|
o.Serial,
|
||||||
|
strings.Join(validSerialOptions, ", "))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if o.PrintSizes != "" {
|
if o.PrintSizes != "" {
|
||||||
valid := isInArray(validPrintSizeOptions, o.PrintSizes)
|
valid := isInArray(validPrintSizeOptions, o.PrintSizes)
|
||||||
if !valid {
|
if !valid {
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ type TargetSpec struct {
|
|||||||
BuildTags []string `json:"build-tags"`
|
BuildTags []string `json:"build-tags"`
|
||||||
GC string `json:"gc"`
|
GC string `json:"gc"`
|
||||||
Scheduler string `json:"scheduler"`
|
Scheduler string `json:"scheduler"`
|
||||||
|
Serial string `json:"serial"` // which serial output to use (uart, usb, none)
|
||||||
Linker string `json:"linker"`
|
Linker string `json:"linker"`
|
||||||
RTLib string `json:"rtlib"` // compiler runtime library (libgcc, compiler-rt)
|
RTLib string `json:"rtlib"` // compiler runtime library (libgcc, compiler-rt)
|
||||||
Libc string `json:"libc"`
|
Libc string `json:"libc"`
|
||||||
@@ -40,10 +41,12 @@ type TargetSpec struct {
|
|||||||
LDFlags []string `json:"ldflags"`
|
LDFlags []string `json:"ldflags"`
|
||||||
LinkerScript string `json:"linkerscript"`
|
LinkerScript string `json:"linkerscript"`
|
||||||
ExtraFiles []string `json:"extra-files"`
|
ExtraFiles []string `json:"extra-files"`
|
||||||
|
RP2040BootPatch *bool `json:"rp2040-boot-patch"` // Patch RP2040 2nd stage bootloader checksum
|
||||||
Emulator []string `json:"emulator" override:"copy"` // inherited Emulator must not be append
|
Emulator []string `json:"emulator" override:"copy"` // inherited Emulator must not be append
|
||||||
FlashCommand string `json:"flash-command"`
|
FlashCommand string `json:"flash-command"`
|
||||||
GDB []string `json:"gdb"`
|
GDB []string `json:"gdb"`
|
||||||
PortReset string `json:"flash-1200-bps-reset"`
|
PortReset string `json:"flash-1200-bps-reset"`
|
||||||
|
SerialPort []string `json:"serial-port"` // serial port IDs in the form "acm:vid:pid" or "usb:vid:pid"
|
||||||
FlashMethod string `json:"flash-method"`
|
FlashMethod string `json:"flash-method"`
|
||||||
FlashVolume string `json:"msd-volume-name"`
|
FlashVolume string `json:"msd-volume-name"`
|
||||||
FlashFilename string `json:"msd-firmware-name"`
|
FlashFilename string `json:"msd-firmware-name"`
|
||||||
|
|||||||
+12
-4
@@ -23,7 +23,7 @@ import (
|
|||||||
// Version of the compiler pacakge. Must be incremented each time the compiler
|
// Version of the compiler pacakge. Must be incremented each time the compiler
|
||||||
// package changes in a way that affects the generated LLVM module.
|
// package changes in a way that affects the generated LLVM module.
|
||||||
// This version is independent of the TinyGo version number.
|
// This version is independent of the TinyGo version number.
|
||||||
const Version = 10 // last change: context parameter in go wrapper
|
const Version = 12 // last change: implement syscall.rawSyscallNoError
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
llvm.InitializeAllTargets()
|
llvm.InitializeAllTargets()
|
||||||
@@ -715,11 +715,11 @@ func (c *compilerContext) createPackage(irbuilder llvm.Builder, pkg *ssa.Package
|
|||||||
member := pkg.Members[name]
|
member := pkg.Members[name]
|
||||||
switch member := member.(type) {
|
switch member := member.(type) {
|
||||||
case *ssa.Function:
|
case *ssa.Function:
|
||||||
|
// Create the function definition.
|
||||||
|
b := newBuilder(c, irbuilder, member)
|
||||||
if member.Blocks == nil {
|
if member.Blocks == nil {
|
||||||
continue // external function
|
continue // external function
|
||||||
}
|
}
|
||||||
// Create the function definition.
|
|
||||||
b := newBuilder(c, irbuilder, member)
|
|
||||||
b.createFunction()
|
b.createFunction()
|
||||||
case *ssa.Type:
|
case *ssa.Type:
|
||||||
if types.IsInterface(member.Type()) {
|
if types.IsInterface(member.Type()) {
|
||||||
@@ -758,10 +758,13 @@ func (c *compilerContext) createPackage(irbuilder llvm.Builder, pkg *ssa.Package
|
|||||||
case *ssa.Global:
|
case *ssa.Global:
|
||||||
// Global variable.
|
// Global variable.
|
||||||
info := c.getGlobalInfo(member)
|
info := c.getGlobalInfo(member)
|
||||||
|
global := c.getGlobal(member)
|
||||||
if !info.extern {
|
if !info.extern {
|
||||||
global := c.getGlobal(member)
|
|
||||||
global.SetInitializer(llvm.ConstNull(global.Type().ElementType()))
|
global.SetInitializer(llvm.ConstNull(global.Type().ElementType()))
|
||||||
global.SetVisibility(llvm.HiddenVisibility)
|
global.SetVisibility(llvm.HiddenVisibility)
|
||||||
|
if info.section != "" {
|
||||||
|
global.SetSection(info.section)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -787,6 +790,9 @@ func (b *builder) createFunction() {
|
|||||||
b.llvmFn.SetVisibility(llvm.HiddenVisibility)
|
b.llvmFn.SetVisibility(llvm.HiddenVisibility)
|
||||||
b.llvmFn.SetUnnamedAddr(true)
|
b.llvmFn.SetUnnamedAddr(true)
|
||||||
}
|
}
|
||||||
|
if b.info.section != "" {
|
||||||
|
b.llvmFn.SetSection(b.info.section)
|
||||||
|
}
|
||||||
if b.info.exported && strings.HasPrefix(b.Triple, "wasm") {
|
if b.info.exported && strings.HasPrefix(b.Triple, "wasm") {
|
||||||
// Set the exported name. This is necessary for WebAssembly because
|
// Set the exported name. This is necessary for WebAssembly because
|
||||||
// otherwise the function is not exported.
|
// otherwise the function is not exported.
|
||||||
@@ -1304,6 +1310,8 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error)
|
|||||||
return b.emitCSROperation(instr)
|
return b.emitCSROperation(instr)
|
||||||
case strings.HasPrefix(name, "syscall.Syscall"):
|
case strings.HasPrefix(name, "syscall.Syscall"):
|
||||||
return b.createSyscall(instr)
|
return b.createSyscall(instr)
|
||||||
|
case strings.HasPrefix(name, "syscall.rawSyscallNoError"):
|
||||||
|
return b.createRawSyscallNoError(instr)
|
||||||
case strings.HasPrefix(name, "runtime/volatile.Load"):
|
case strings.HasPrefix(name, "runtime/volatile.Load"):
|
||||||
return b.createVolatileLoad(instr)
|
return b.createVolatileLoad(instr)
|
||||||
case strings.HasPrefix(name, "runtime/volatile.Store"):
|
case strings.HasPrefix(name, "runtime/volatile.Store"):
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ func TestCompiler(t *testing.T) {
|
|||||||
{"float.go", ""},
|
{"float.go", ""},
|
||||||
{"interface.go", ""},
|
{"interface.go", ""},
|
||||||
{"func.go", ""},
|
{"func.go", ""},
|
||||||
|
{"pragma.go", ""},
|
||||||
{"goroutine.go", "wasm"},
|
{"goroutine.go", "wasm"},
|
||||||
{"goroutine.go", "cortex-m-qemu"},
|
{"goroutine.go", "cortex-m-qemu"},
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-2
@@ -311,10 +311,21 @@ func (c *compilerContext) getInterfaceMethodSet(typ types.Type) llvm.Value {
|
|||||||
// used during the interface lowering pass.
|
// used during the interface lowering pass.
|
||||||
func (c *compilerContext) getMethodSignature(method *types.Func) llvm.Value {
|
func (c *compilerContext) getMethodSignature(method *types.Func) llvm.Value {
|
||||||
signature := methodSignature(method)
|
signature := methodSignature(method)
|
||||||
signatureGlobal := c.mod.NamedGlobal("func " + signature)
|
var globalName string
|
||||||
|
if token.IsExported(method.Name()) {
|
||||||
|
globalName = "reflect/methods." + signature
|
||||||
|
} else {
|
||||||
|
globalName = method.Type().(*types.Signature).Recv().Pkg().Path() + ".$methods." + signature
|
||||||
|
}
|
||||||
|
signatureGlobal := c.mod.NamedGlobal(globalName)
|
||||||
if signatureGlobal.IsNil() {
|
if signatureGlobal.IsNil() {
|
||||||
signatureGlobal = llvm.AddGlobal(c.mod, c.ctx.Int8Type(), "func "+signature)
|
// TODO: put something useful in these globals, such as the method
|
||||||
|
// signature. Useful to one day implement reflect.Value.Method(n).
|
||||||
|
signatureGlobal = llvm.AddGlobal(c.mod, c.ctx.Int8Type(), globalName)
|
||||||
|
signatureGlobal.SetInitializer(llvm.ConstInt(c.ctx.Int8Type(), 0, false))
|
||||||
|
signatureGlobal.SetLinkage(llvm.LinkOnceODRLinkage)
|
||||||
signatureGlobal.SetGlobalConstant(true)
|
signatureGlobal.SetGlobalConstant(true)
|
||||||
|
signatureGlobal.SetAlignment(1)
|
||||||
}
|
}
|
||||||
return signatureGlobal
|
return signatureGlobal
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ type functionInfo struct {
|
|||||||
module string // go:wasm-module
|
module string // go:wasm-module
|
||||||
importName string // go:linkname, go:export - The name the developer assigns
|
importName string // go:linkname, go:export - The name the developer assigns
|
||||||
linkName string // go:linkname, go:export - The name that we map for the particular module -> importName
|
linkName string // go:linkname, go:export - The name that we map for the particular module -> importName
|
||||||
|
section string // go:section - object file section name
|
||||||
exported bool // go:export, CGo
|
exported bool // go:export, CGo
|
||||||
nobounds bool // go:nobounds
|
nobounds bool // go:nobounds
|
||||||
variadic bool // go:variadic (CGo only)
|
variadic bool // go:variadic (CGo only)
|
||||||
@@ -270,6 +271,10 @@ func (info *functionInfo) parsePragmas(f *ssa.Function) {
|
|||||||
if hasUnsafeImport(f.Pkg.Pkg) {
|
if hasUnsafeImport(f.Pkg.Pkg) {
|
||||||
info.linkName = parts[2]
|
info.linkName = parts[2]
|
||||||
}
|
}
|
||||||
|
case "//go:section":
|
||||||
|
if len(parts) == 2 && hasUnsafeImport(f.Pkg.Pkg) {
|
||||||
|
info.section = parts[1]
|
||||||
|
}
|
||||||
case "//go:nobounds":
|
case "//go:nobounds":
|
||||||
// Skip bounds checking in this function. Useful for some
|
// Skip bounds checking in this function. Useful for some
|
||||||
// runtime functions.
|
// runtime functions.
|
||||||
@@ -325,6 +330,7 @@ type globalInfo struct {
|
|||||||
linkName string // go:extern
|
linkName string // go:extern
|
||||||
extern bool // go:extern
|
extern bool // go:extern
|
||||||
align int // go:align
|
align int // go:align
|
||||||
|
section string // go:section
|
||||||
}
|
}
|
||||||
|
|
||||||
// loadASTComments loads comments on globals from the AST, for use later in the
|
// loadASTComments loads comments on globals from the AST, for use later in the
|
||||||
@@ -438,6 +444,10 @@ func (info *globalInfo) parsePragmas(doc *ast.CommentGroup) {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
info.align = align
|
info.align = align
|
||||||
}
|
}
|
||||||
|
case "//go:section":
|
||||||
|
if len(parts) == 2 {
|
||||||
|
info.section = parts[1]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+30
-8
@@ -10,11 +10,11 @@ import (
|
|||||||
"tinygo.org/x/go-llvm"
|
"tinygo.org/x/go-llvm"
|
||||||
)
|
)
|
||||||
|
|
||||||
// createSyscall emits an inline system call instruction, depending on the
|
// createRawSyscall creates a system call with the provided system call number
|
||||||
// target OS/arch.
|
// and returns the result as a single integer (the system call result). The
|
||||||
func (b *builder) createSyscall(call *ssa.CallCommon) (llvm.Value, error) {
|
// result is not further interpreted.
|
||||||
|
func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) {
|
||||||
num := b.getValue(call.Args[0])
|
num := b.getValue(call.Args[0])
|
||||||
var syscallResult llvm.Value
|
|
||||||
switch {
|
switch {
|
||||||
case b.GOARCH == "amd64":
|
case b.GOARCH == "amd64":
|
||||||
if b.GOOS == "darwin" {
|
if b.GOOS == "darwin" {
|
||||||
@@ -57,7 +57,7 @@ func (b *builder) createSyscall(call *ssa.CallCommon) (llvm.Value, error) {
|
|||||||
constraints += ",~{rcx},~{r11}"
|
constraints += ",~{rcx},~{r11}"
|
||||||
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
|
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
|
||||||
target := llvm.InlineAsm(fnType, "syscall", constraints, true, false, llvm.InlineAsmDialectIntel)
|
target := llvm.InlineAsm(fnType, "syscall", constraints, true, false, llvm.InlineAsmDialectIntel)
|
||||||
syscallResult = b.CreateCall(target, args, "")
|
return b.CreateCall(target, args, ""), nil
|
||||||
case b.GOARCH == "386" && b.GOOS == "linux":
|
case b.GOARCH == "386" && b.GOOS == "linux":
|
||||||
// Sources:
|
// Sources:
|
||||||
// syscall(2) man page
|
// syscall(2) man page
|
||||||
@@ -83,7 +83,7 @@ func (b *builder) createSyscall(call *ssa.CallCommon) (llvm.Value, error) {
|
|||||||
}
|
}
|
||||||
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
|
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
|
||||||
target := llvm.InlineAsm(fnType, "int 0x80", constraints, true, false, llvm.InlineAsmDialectIntel)
|
target := llvm.InlineAsm(fnType, "int 0x80", constraints, true, false, llvm.InlineAsmDialectIntel)
|
||||||
syscallResult = b.CreateCall(target, args, "")
|
return b.CreateCall(target, args, ""), nil
|
||||||
case b.GOARCH == "arm" && b.GOOS == "linux":
|
case b.GOARCH == "arm" && b.GOOS == "linux":
|
||||||
// Implement the EABI system call convention for Linux.
|
// Implement the EABI system call convention for Linux.
|
||||||
// Source: syscall(2) man page.
|
// Source: syscall(2) man page.
|
||||||
@@ -115,7 +115,7 @@ func (b *builder) createSyscall(call *ssa.CallCommon) (llvm.Value, error) {
|
|||||||
}
|
}
|
||||||
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
|
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
|
||||||
target := llvm.InlineAsm(fnType, "svc #0", constraints, true, false, 0)
|
target := llvm.InlineAsm(fnType, "svc #0", constraints, true, false, 0)
|
||||||
syscallResult = b.CreateCall(target, args, "")
|
return b.CreateCall(target, args, ""), nil
|
||||||
case b.GOARCH == "arm64" && b.GOOS == "linux":
|
case b.GOARCH == "arm64" && b.GOOS == "linux":
|
||||||
// Source: syscall(2) man page.
|
// Source: syscall(2) man page.
|
||||||
args := []llvm.Value{}
|
args := []llvm.Value{}
|
||||||
@@ -147,10 +147,19 @@ func (b *builder) createSyscall(call *ssa.CallCommon) (llvm.Value, error) {
|
|||||||
constraints += ",~{x16},~{x17}" // scratch registers
|
constraints += ",~{x16},~{x17}" // scratch registers
|
||||||
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
|
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
|
||||||
target := llvm.InlineAsm(fnType, "svc #0", constraints, true, false, 0)
|
target := llvm.InlineAsm(fnType, "svc #0", constraints, true, false, 0)
|
||||||
syscallResult = b.CreateCall(target, args, "")
|
return b.CreateCall(target, args, ""), nil
|
||||||
default:
|
default:
|
||||||
return llvm.Value{}, b.makeError(call.Pos(), "unknown GOOS/GOARCH for syscall: "+b.GOOS+"/"+b.GOARCH)
|
return llvm.Value{}, b.makeError(call.Pos(), "unknown GOOS/GOARCH for syscall: "+b.GOOS+"/"+b.GOARCH)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// createSyscall emits instructions for the syscall.Syscall* family of
|
||||||
|
// functions, depending on the target OS/arch.
|
||||||
|
func (b *builder) createSyscall(call *ssa.CallCommon) (llvm.Value, error) {
|
||||||
|
syscallResult, err := b.createRawSyscall(call)
|
||||||
|
if err != nil {
|
||||||
|
return syscallResult, err
|
||||||
|
}
|
||||||
switch b.GOOS {
|
switch b.GOOS {
|
||||||
case "linux", "freebsd":
|
case "linux", "freebsd":
|
||||||
// Return values: r0, r1 uintptr, err Errno
|
// Return values: r0, r1 uintptr, err Errno
|
||||||
@@ -190,3 +199,16 @@ func (b *builder) createSyscall(call *ssa.CallCommon) (llvm.Value, error) {
|
|||||||
return llvm.Value{}, b.makeError(call.Pos(), "unknown GOOS/GOARCH for syscall: "+b.GOOS+"/"+b.GOARCH)
|
return llvm.Value{}, b.makeError(call.Pos(), "unknown GOOS/GOARCH for syscall: "+b.GOOS+"/"+b.GOARCH)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// createRawSyscallNoError emits instructions for the Linux-specific
|
||||||
|
// syscall.rawSyscallNoError function.
|
||||||
|
func (b *builder) createRawSyscallNoError(call *ssa.CallCommon) (llvm.Value, error) {
|
||||||
|
syscallResult, err := b.createRawSyscall(call)
|
||||||
|
if err != nil {
|
||||||
|
return syscallResult, err
|
||||||
|
}
|
||||||
|
retval := llvm.ConstNull(b.ctx.StructType([]llvm.Type{b.uintptrType, b.uintptrType}, false))
|
||||||
|
retval = b.CreateInsertValue(retval, syscallResult, 0, "")
|
||||||
|
retval = b.CreateInsertValue(retval, llvm.ConstInt(b.uintptrType, 0, false), 1, "")
|
||||||
|
return retval, nil
|
||||||
|
}
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@ target triple = "armv7m-none-eabi"
|
|||||||
|
|
||||||
%runtime.channel = type { i32, i32, i8, %runtime.channelBlockedList*, i32, i32, i32, i8* }
|
%runtime.channel = type { i32, i32, i8, %runtime.channelBlockedList*, i32, i32, i32, i8* }
|
||||||
%runtime.channelBlockedList = type { %runtime.channelBlockedList*, %"internal/task.Task"*, %runtime.chanSelectState*, { %runtime.channelBlockedList*, i32, i32 } }
|
%runtime.channelBlockedList = type { %runtime.channelBlockedList*, %"internal/task.Task"*, %runtime.chanSelectState*, { %runtime.channelBlockedList*, i32, i32 } }
|
||||||
%"internal/task.Task" = type { %"internal/task.Task"*, i8*, i32, %"internal/task.state" }
|
%"internal/task.Task" = type { %"internal/task.Task"*, i8*, i64, %"internal/task.state" }
|
||||||
%"internal/task.state" = type { i32, i32* }
|
%"internal/task.state" = type { i32, i32* }
|
||||||
%runtime.chanSelectState = type { %runtime.channel*, i8* }
|
%runtime.chanSelectState = type { %runtime.channel*, i8* }
|
||||||
|
|
||||||
|
|||||||
Vendored
+1
-1
@@ -6,7 +6,7 @@ target triple = "wasm32--wasi"
|
|||||||
%runtime.funcValueWithSignature = type { i32, i8* }
|
%runtime.funcValueWithSignature = type { i32, i8* }
|
||||||
%runtime.channel = type { i32, i32, i8, %runtime.channelBlockedList*, i32, i32, i32, i8* }
|
%runtime.channel = type { i32, i32, i8, %runtime.channelBlockedList*, i32, i32, i32, i8* }
|
||||||
%runtime.channelBlockedList = type { %runtime.channelBlockedList*, %"internal/task.Task"*, %runtime.chanSelectState*, { %runtime.channelBlockedList*, i32, i32 } }
|
%runtime.channelBlockedList = type { %runtime.channelBlockedList*, %"internal/task.Task"*, %runtime.chanSelectState*, { %runtime.channelBlockedList*, i32, i32 } }
|
||||||
%"internal/task.Task" = type { %"internal/task.Task"*, i8*, i32, %"internal/task.state" }
|
%"internal/task.Task" = type { %"internal/task.Task"*, i8*, i64, %"internal/task.state" }
|
||||||
%"internal/task.state" = type { i8* }
|
%"internal/task.state" = type { i8* }
|
||||||
%runtime.chanSelectState = type { %runtime.channel*, i8* }
|
%runtime.chanSelectState = type { %runtime.channel*, i8* }
|
||||||
|
|
||||||
|
|||||||
Vendored
+6
-6
@@ -13,15 +13,15 @@ target triple = "wasm32--wasi"
|
|||||||
@"reflect/types.type:pointer:named:error" = linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID* @"reflect/types.type:named:error", i32 0, %runtime.interfaceMethodInfo* null, %runtime.typecodeID* null }
|
@"reflect/types.type:pointer:named:error" = linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID* @"reflect/types.type:named:error", i32 0, %runtime.interfaceMethodInfo* null, %runtime.typecodeID* null }
|
||||||
@"reflect/types.type:named:error" = linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID* @"reflect/types.type:interface:{Error:func:{}{basic:string}}", i32 0, %runtime.interfaceMethodInfo* null, %runtime.typecodeID* @"reflect/types.type:pointer:named:error" }
|
@"reflect/types.type:named:error" = linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID* @"reflect/types.type:interface:{Error:func:{}{basic:string}}", i32 0, %runtime.interfaceMethodInfo* null, %runtime.typecodeID* @"reflect/types.type:pointer:named:error" }
|
||||||
@"reflect/types.type:interface:{Error:func:{}{basic:string}}" = linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID* bitcast ([1 x i8*]* @"reflect/types.interface:interface{Error() string}$interface" to %runtime.typecodeID*), i32 0, %runtime.interfaceMethodInfo* null, %runtime.typecodeID* @"reflect/types.type:pointer:interface:{Error:func:{}{basic:string}}" }
|
@"reflect/types.type:interface:{Error:func:{}{basic:string}}" = linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID* bitcast ([1 x i8*]* @"reflect/types.interface:interface{Error() string}$interface" to %runtime.typecodeID*), i32 0, %runtime.interfaceMethodInfo* null, %runtime.typecodeID* @"reflect/types.type:pointer:interface:{Error:func:{}{basic:string}}" }
|
||||||
@"func Error() string" = external constant i8
|
@"reflect/methods.Error() string" = linkonce_odr constant i8 0, align 1
|
||||||
@"reflect/types.interface:interface{Error() string}$interface" = linkonce_odr constant [1 x i8*] [i8* @"func Error() string"]
|
@"reflect/types.interface:interface{Error() string}$interface" = linkonce_odr constant [1 x i8*] [i8* @"reflect/methods.Error() string"]
|
||||||
@"reflect/types.type:pointer:interface:{Error:func:{}{basic:string}}" = linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID* @"reflect/types.type:interface:{Error:func:{}{basic:string}}", i32 0, %runtime.interfaceMethodInfo* null, %runtime.typecodeID* null }
|
@"reflect/types.type:pointer:interface:{Error:func:{}{basic:string}}" = linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID* @"reflect/types.type:interface:{Error:func:{}{basic:string}}", i32 0, %runtime.interfaceMethodInfo* null, %runtime.typecodeID* null }
|
||||||
@"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}" = linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID* @"reflect/types.type:interface:{String:func:{}{basic:string}}", i32 0, %runtime.interfaceMethodInfo* null, %runtime.typecodeID* null }
|
@"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}" = linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID* @"reflect/types.type:interface:{String:func:{}{basic:string}}", i32 0, %runtime.interfaceMethodInfo* null, %runtime.typecodeID* null }
|
||||||
@"reflect/types.type:interface:{String:func:{}{basic:string}}" = linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID* bitcast ([1 x i8*]* @"reflect/types.interface:interface{String() string}$interface" to %runtime.typecodeID*), i32 0, %runtime.interfaceMethodInfo* null, %runtime.typecodeID* @"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}" }
|
@"reflect/types.type:interface:{String:func:{}{basic:string}}" = linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID* bitcast ([1 x i8*]* @"reflect/types.interface:interface{String() string}$interface" to %runtime.typecodeID*), i32 0, %runtime.interfaceMethodInfo* null, %runtime.typecodeID* @"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}" }
|
||||||
@"func String() string" = external constant i8
|
@"reflect/methods.String() string" = linkonce_odr constant i8 0, align 1
|
||||||
@"reflect/types.interface:interface{String() string}$interface" = linkonce_odr constant [1 x i8*] [i8* @"func String() string"]
|
@"reflect/types.interface:interface{String() string}$interface" = linkonce_odr constant [1 x i8*] [i8* @"reflect/methods.String() string"]
|
||||||
@"reflect/types.typeid:basic:int" = external constant i8
|
@"reflect/types.typeid:basic:int" = external constant i8
|
||||||
@"error$interface" = linkonce_odr constant [1 x i8*] [i8* @"func Error() string"]
|
@"error$interface" = linkonce_odr constant [1 x i8*] [i8* @"reflect/methods.Error() string"]
|
||||||
|
|
||||||
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*)
|
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*)
|
||||||
|
|
||||||
@@ -92,7 +92,7 @@ typeassert.next: ; preds = %typeassert.ok, %ent
|
|||||||
|
|
||||||
define hidden %runtime._string @main.callErrorMethod(i32 %itf.typecode, i8* %itf.value, i8* %context, i8* %parentHandle) unnamed_addr {
|
define hidden %runtime._string @main.callErrorMethod(i32 %itf.typecode, i8* %itf.value, i8* %context, i8* %parentHandle) unnamed_addr {
|
||||||
entry:
|
entry:
|
||||||
%invoke.func = call i32 @runtime.interfaceMethod(i32 %itf.typecode, i8** getelementptr inbounds ([1 x i8*], [1 x i8*]* @"error$interface", i32 0, i32 0), i8* nonnull @"func Error() string", i8* undef, i8* null)
|
%invoke.func = call i32 @runtime.interfaceMethod(i32 %itf.typecode, i8** getelementptr inbounds ([1 x i8*], [1 x i8*]* @"error$interface", i32 0, i32 0), i8* nonnull @"reflect/methods.Error() string", i8* undef, i8* null)
|
||||||
%invoke.func.cast = inttoptr i32 %invoke.func to %runtime._string (i8*, i8*, i8*)*
|
%invoke.func.cast = inttoptr i32 %invoke.func to %runtime._string (i8*, i8*, i8*)*
|
||||||
%0 = call %runtime._string %invoke.func.cast(i8* %itf.value, i8* undef, i8* undef)
|
%0 = call %runtime._string %invoke.func.cast(i8* %itf.value, i8* undef, i8* undef)
|
||||||
ret %runtime._string %0
|
ret %runtime._string %0
|
||||||
|
|||||||
Vendored
+66
@@ -0,0 +1,66 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import _ "unsafe"
|
||||||
|
|
||||||
|
// Creates an external global with name extern_global.
|
||||||
|
//go:extern extern_global
|
||||||
|
var externGlobal [0]byte
|
||||||
|
|
||||||
|
// Creates a
|
||||||
|
//go:align 32
|
||||||
|
var alignedGlobal [4]uint32
|
||||||
|
|
||||||
|
// Test conflicting pragmas (the last one counts).
|
||||||
|
//go:align 64
|
||||||
|
//go:align 16
|
||||||
|
var alignedGlobal16 [4]uint32
|
||||||
|
|
||||||
|
// Test exported functions.
|
||||||
|
//export extern_func
|
||||||
|
func externFunc() {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define a function in a different package using go:linkname.
|
||||||
|
//go:linkname withLinkageName1 somepkg.someFunction1
|
||||||
|
func withLinkageName1() {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Import a function from a different package using go:linkname.
|
||||||
|
//go:linkname withLinkageName2 somepkg.someFunction2
|
||||||
|
func withLinkageName2()
|
||||||
|
|
||||||
|
// Function has an 'inline hint', similar to the inline keyword in C.
|
||||||
|
//go:inline
|
||||||
|
func inlineFunc() {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function should never be inlined, equivalent to GCC
|
||||||
|
// __attribute__((noinline)).
|
||||||
|
//go:noinline
|
||||||
|
func noinlineFunc() {
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function should have the specified section.
|
||||||
|
//go:section .special_function_section
|
||||||
|
func functionInSection() {
|
||||||
|
}
|
||||||
|
|
||||||
|
//export exportedFunctionInSection
|
||||||
|
//go:section .special_function_section
|
||||||
|
func exportedFunctionInSection() {
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function should not: it's only a declaration and not a definition.
|
||||||
|
//go:section .special_function_section
|
||||||
|
func undefinedFunctionNotInSection()
|
||||||
|
|
||||||
|
//go:section .special_global_section
|
||||||
|
var globalInSection uint32
|
||||||
|
|
||||||
|
//go:section .special_global_section
|
||||||
|
//go:extern undefinedGlobalNotInSection
|
||||||
|
var undefinedGlobalNotInSection uint32
|
||||||
|
|
||||||
|
//go:align 1024
|
||||||
|
//go:section .global_section
|
||||||
|
var multipleGlobalPragmas uint32
|
||||||
Vendored
+59
@@ -0,0 +1,59 @@
|
|||||||
|
; ModuleID = 'pragma.go'
|
||||||
|
source_filename = "pragma.go"
|
||||||
|
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
|
||||||
|
target triple = "wasm32--wasi"
|
||||||
|
|
||||||
|
@extern_global = external global [0 x i8], align 1
|
||||||
|
@main.alignedGlobal = hidden global [4 x i32] zeroinitializer, align 32
|
||||||
|
@main.alignedGlobal16 = hidden global [4 x i32] zeroinitializer, align 16
|
||||||
|
@main.globalInSection = hidden global i32 0, section ".special_global_section", align 4
|
||||||
|
@undefinedGlobalNotInSection = external global i32, align 4
|
||||||
|
@main.multipleGlobalPragmas = hidden global i32 0, section ".global_section", align 1024
|
||||||
|
|
||||||
|
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*)
|
||||||
|
|
||||||
|
define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr {
|
||||||
|
entry:
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @extern_func() #0 {
|
||||||
|
entry:
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define hidden void @somepkg.someFunction1(i8* %context, i8* %parentHandle) unnamed_addr {
|
||||||
|
entry:
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @somepkg.someFunction2(i8*, i8*)
|
||||||
|
|
||||||
|
; Function Attrs: inlinehint
|
||||||
|
define hidden void @main.inlineFunc(i8* %context, i8* %parentHandle) unnamed_addr #1 {
|
||||||
|
entry:
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; Function Attrs: noinline
|
||||||
|
define hidden void @main.noinlineFunc(i8* %context, i8* %parentHandle) unnamed_addr #2 {
|
||||||
|
entry:
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define hidden void @main.functionInSection(i8* %context, i8* %parentHandle) unnamed_addr section ".special_function_section" {
|
||||||
|
entry:
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @exportedFunctionInSection() #3 section ".special_function_section" {
|
||||||
|
entry:
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @main.undefinedFunctionNotInSection(i8*, i8*)
|
||||||
|
|
||||||
|
attributes #0 = { "wasm-export-name"="extern_func" }
|
||||||
|
attributes #1 = { inlinehint }
|
||||||
|
attributes #2 = { noinline }
|
||||||
|
attributes #3 = { "wasm-export-name"="exportedFunctionInSection" }
|
||||||
+1
-1
@@ -12,7 +12,7 @@ import (
|
|||||||
|
|
||||||
// Version of TinyGo.
|
// Version of TinyGo.
|
||||||
// Update this value before release of new version of software.
|
// Update this value before release of new version of software.
|
||||||
const Version = "0.19.0-dev"
|
const Version = "0.20.0-dev"
|
||||||
|
|
||||||
// GetGorootVersion returns the major and minor version for a given GOROOT path.
|
// GetGorootVersion returns the major and minor version for a given GOROOT path.
|
||||||
// If the goroot cannot be determined, (0, 0) is returned.
|
// If the goroot cannot be determined, (0, 0) is returned.
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ func (r *runner) errorAt(inst instruction, err error) *Error {
|
|||||||
pos := getPosition(inst.llvmInst)
|
pos := getPosition(inst.llvmInst)
|
||||||
return &Error{
|
return &Error{
|
||||||
ImportPath: r.pkgName,
|
ImportPath: r.pkgName,
|
||||||
|
Inst: inst.llvmInst,
|
||||||
Pos: pos,
|
Pos: pos,
|
||||||
Err: err,
|
Err: err,
|
||||||
Traceback: []ErrorLine{{pos, inst.llvmInst}},
|
Traceback: []ErrorLine{{pos, inst.llvmInst}},
|
||||||
|
|||||||
+34
-3
@@ -15,7 +15,7 @@ import (
|
|||||||
// package is changed in a way that affects the output so that cached package
|
// package is changed in a way that affects the output so that cached package
|
||||||
// builds will be invalidated.
|
// builds will be invalidated.
|
||||||
// This version is independent of the TinyGo version number.
|
// This version is independent of the TinyGo version number.
|
||||||
const Version = 1
|
const Version = 2 // last change: fix GEP on untyped pointers
|
||||||
|
|
||||||
// Enable extra checks, which should be disabled by default.
|
// Enable extra checks, which should be disabled by default.
|
||||||
// This may help track down bugs by adding a few more sanity checks.
|
// This may help track down bugs by adding a few more sanity checks.
|
||||||
@@ -110,17 +110,26 @@ func Run(mod llvm.Module, debug bool) error {
|
|||||||
fmt.Fprintln(os.Stderr, "call:", fn.Name())
|
fmt.Fprintln(os.Stderr, "call:", fn.Name())
|
||||||
}
|
}
|
||||||
_, mem, callErr := r.run(r.getFunction(fn), nil, nil, " ")
|
_, mem, callErr := r.run(r.getFunction(fn), nil, nil, " ")
|
||||||
|
call.EraseFromParentAsInstruction()
|
||||||
if callErr != nil {
|
if callErr != nil {
|
||||||
if isRecoverableError(callErr.Err) {
|
if isRecoverableError(callErr.Err) {
|
||||||
if r.debug {
|
if r.debug {
|
||||||
fmt.Fprintln(os.Stderr, "not interpreting", r.pkgName, "because of error:", callErr.Error())
|
fmt.Fprintln(os.Stderr, "not interpreting", r.pkgName, "because of error:", callErr.Error())
|
||||||
}
|
}
|
||||||
|
// Remove instructions that were created as part of interpreting
|
||||||
|
// the package.
|
||||||
mem.revert()
|
mem.revert()
|
||||||
|
// Create a call to the package initializer (which was
|
||||||
|
// previously deleted).
|
||||||
|
i8undef := llvm.Undef(r.i8ptrType)
|
||||||
|
r.builder.CreateCall(fn, []llvm.Value{i8undef, i8undef}, "")
|
||||||
|
// Make sure that any globals touched by the package
|
||||||
|
// initializer, won't be accessed by later package initializers.
|
||||||
|
r.markExternalLoad(fn)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return callErr
|
return callErr
|
||||||
}
|
}
|
||||||
call.EraseFromParentAsInstruction()
|
|
||||||
for index, obj := range mem.objects {
|
for index, obj := range mem.objects {
|
||||||
r.objects[index] = obj
|
r.objects[index] = obj
|
||||||
}
|
}
|
||||||
@@ -129,7 +138,7 @@ func Run(mod llvm.Module, debug bool) error {
|
|||||||
|
|
||||||
// Update all global variables in the LLVM module.
|
// Update all global variables in the LLVM module.
|
||||||
mem := memoryView{r: r}
|
mem := memoryView{r: r}
|
||||||
for _, obj := range r.objects {
|
for i, obj := range r.objects {
|
||||||
if obj.llvmGlobal.IsNil() {
|
if obj.llvmGlobal.IsNil() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -159,6 +168,12 @@ func Run(mod llvm.Module, debug bool) error {
|
|||||||
name := obj.llvmGlobal.Name()
|
name := obj.llvmGlobal.Name()
|
||||||
obj.llvmGlobal.EraseFromParentAsGlobal()
|
obj.llvmGlobal.EraseFromParentAsGlobal()
|
||||||
newGlobal.SetName(name)
|
newGlobal.SetName(name)
|
||||||
|
|
||||||
|
// Update interp-internal references.
|
||||||
|
delete(r.globals, obj.llvmGlobal)
|
||||||
|
obj.llvmGlobal = newGlobal
|
||||||
|
r.globals[newGlobal] = i
|
||||||
|
r.objects[i] = obj
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -264,3 +279,19 @@ func (r *runner) getFunction(llvmFn llvm.Value) *function {
|
|||||||
r.functionCache[llvmFn] = fn
|
r.functionCache[llvmFn] = fn
|
||||||
return fn
|
return fn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// markExternalLoad marks the given llvmValue as being loaded externally. This
|
||||||
|
// is primarily used to mark package initializers that could not be run at
|
||||||
|
// compile time. As an example, a package initialize might store to a global
|
||||||
|
// variable. Another package initializer might read from the same global
|
||||||
|
// variable. By marking this function as being run at runtime, that load
|
||||||
|
// instruction will need to be run at runtime instead of at compile time.
|
||||||
|
func (r *runner) markExternalLoad(llvmValue llvm.Value) {
|
||||||
|
mem := memoryView{r: r}
|
||||||
|
mem.markExternalLoad(llvmValue)
|
||||||
|
for index, obj := range mem.objects {
|
||||||
|
if obj.marked > r.objects[index].marked {
|
||||||
|
r.objects[index].marked = obj.marked
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ func TestInterp(t *testing.T) {
|
|||||||
"slice-copy",
|
"slice-copy",
|
||||||
"consteval",
|
"consteval",
|
||||||
"interface",
|
"interface",
|
||||||
|
"revert",
|
||||||
} {
|
} {
|
||||||
name := name // make tc local to this closure
|
name := name // make tc local to this closure
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
|
|||||||
@@ -572,6 +572,17 @@ func (v pointerValue) toLLVMValue(llvmType llvm.Type, mem *memoryView) (llvm.Val
|
|||||||
}
|
}
|
||||||
|
|
||||||
if llvmType.IsNil() {
|
if llvmType.IsNil() {
|
||||||
|
if v.offset() != 0 {
|
||||||
|
// If there is an offset, make sure to use a GEP to index into the
|
||||||
|
// pointer. Because there is no expected type, we use whatever is
|
||||||
|
// most convenient: an *i8 type. It is trivial to index byte-wise.
|
||||||
|
if llvmValue.Type() != mem.r.i8ptrType {
|
||||||
|
llvmValue = llvm.ConstBitCast(llvmValue, mem.r.i8ptrType)
|
||||||
|
}
|
||||||
|
llvmValue = llvm.ConstInBoundsGEP(llvmValue, []llvm.Value{
|
||||||
|
llvm.ConstInt(llvmValue.Type().Context().Int32Type(), uint64(v.offset()), false),
|
||||||
|
})
|
||||||
|
}
|
||||||
return llvmValue, nil
|
return llvmValue, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Vendored
+32
@@ -0,0 +1,32 @@
|
|||||||
|
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||||
|
target triple = "x86_64--linux"
|
||||||
|
|
||||||
|
declare void @externalCall(i64)
|
||||||
|
|
||||||
|
@foo.knownAtRuntime = global i64 0
|
||||||
|
@bar.knownAtRuntime = global i64 0
|
||||||
|
|
||||||
|
define void @runtime.initAll() unnamed_addr {
|
||||||
|
entry:
|
||||||
|
call void @foo.init(i8* undef, i8* undef)
|
||||||
|
call void @bar.init(i8* undef, i8* undef)
|
||||||
|
call void @main.init(i8* undef, i8* undef)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define internal void @foo.init(i8* %context, i8* %parentHandle) unnamed_addr {
|
||||||
|
store i64 5, i64* @foo.knownAtRuntime
|
||||||
|
unreachable ; this triggers a revert of @foo.init.
|
||||||
|
}
|
||||||
|
|
||||||
|
define internal void @bar.init(i8* %context, i8* %parentHandle) unnamed_addr {
|
||||||
|
%val = load i64, i64* @foo.knownAtRuntime
|
||||||
|
store i64 %val, i64* @bar.knownAtRuntime
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define internal void @main.init(i8* %context, i8* %parentHandle) unnamed_addr {
|
||||||
|
entry:
|
||||||
|
call void @externalCall(i64 3)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
Vendored
+21
@@ -0,0 +1,21 @@
|
|||||||
|
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||||
|
target triple = "x86_64--linux"
|
||||||
|
|
||||||
|
@foo.knownAtRuntime = local_unnamed_addr global i64 0
|
||||||
|
@bar.knownAtRuntime = local_unnamed_addr global i64 0
|
||||||
|
|
||||||
|
declare void @externalCall(i64) local_unnamed_addr
|
||||||
|
|
||||||
|
define void @runtime.initAll() unnamed_addr {
|
||||||
|
entry:
|
||||||
|
call fastcc void @foo.init(i8* undef, i8* undef)
|
||||||
|
%val = load i64, i64* @foo.knownAtRuntime, align 8
|
||||||
|
store i64 %val, i64* @bar.knownAtRuntime, align 8
|
||||||
|
call void @externalCall(i64 3)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define internal fastcc void @foo.init(i8* %context, i8* %parentHandle) unnamed_addr {
|
||||||
|
store i64 5, i64* @foo.knownAtRuntime, align 8
|
||||||
|
unreachable
|
||||||
|
}
|
||||||
+36
-15
@@ -2,6 +2,14 @@ package loader
|
|||||||
|
|
||||||
// This file constructs a new temporary GOROOT directory by merging both the
|
// This file constructs a new temporary GOROOT directory by merging both the
|
||||||
// standard Go GOROOT and the GOROOT from TinyGo using symlinks.
|
// standard Go GOROOT and the GOROOT from TinyGo using symlinks.
|
||||||
|
//
|
||||||
|
// The goal is to replace specific packages from Go with a TinyGo version. It's
|
||||||
|
// never a partial replacement, either a package is fully replaced or it is not.
|
||||||
|
// This is important because if we did allow to merge packages (e.g. by adding
|
||||||
|
// files to a package), it would lead to a dependency on implementation details
|
||||||
|
// with all the maintenance burden that results in. Only allowing to replace
|
||||||
|
// packages as a whole avoids this as packages are already designed to have a
|
||||||
|
// public (backwards-compatible) API.
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha512"
|
"crypto/sha512"
|
||||||
@@ -139,6 +147,7 @@ func mergeDirectory(goroot, tinygoroot, tmpgoroot, importPath string, overrides
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
hasTinyGoFiles := false
|
||||||
for _, e := range tinygoEntries {
|
for _, e := range tinygoEntries {
|
||||||
if e.IsDir() {
|
if e.IsDir() {
|
||||||
// A directory, so merge this thing.
|
// A directory, so merge this thing.
|
||||||
@@ -154,6 +163,7 @@ func mergeDirectory(goroot, tinygoroot, tmpgoroot, importPath string, overrides
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
hasTinyGoFiles = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,21 +174,30 @@ func mergeDirectory(goroot, tinygoroot, tmpgoroot, importPath string, overrides
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for _, e := range gorootEntries {
|
for _, e := range gorootEntries {
|
||||||
if !e.IsDir() {
|
if e.IsDir() {
|
||||||
// Don't merge in files from Go. Otherwise we'd end up with a
|
if _, ok := overrides[path.Join(importPath, e.Name())+"/"]; ok {
|
||||||
// weird syscall package with files from both roots.
|
// Already included above, so don't bother trying to create this
|
||||||
continue
|
// symlink.
|
||||||
}
|
continue
|
||||||
if _, ok := overrides[path.Join(importPath, e.Name())+"/"]; ok {
|
}
|
||||||
// Already included above, so don't bother trying to create this
|
newname := filepath.Join(tmpgoroot, "src", importPath, e.Name())
|
||||||
// symlink.
|
oldname := filepath.Join(goroot, "src", importPath, e.Name())
|
||||||
continue
|
err := symlink(oldname, newname)
|
||||||
}
|
if err != nil {
|
||||||
newname := filepath.Join(tmpgoroot, "src", importPath, e.Name())
|
return err
|
||||||
oldname := filepath.Join(goroot, "src", importPath, e.Name())
|
}
|
||||||
err := symlink(oldname, newname)
|
} else {
|
||||||
if err != nil {
|
// Only merge files from Go if TinyGo does not have any files.
|
||||||
return err
|
// Otherwise we'd end up with a weird mix from both Go
|
||||||
|
// implementations.
|
||||||
|
if !hasTinyGoFiles {
|
||||||
|
newname := filepath.Join(tmpgoroot, "src", importPath, e.Name())
|
||||||
|
oldname := filepath.Join(goroot, "src", importPath, e.Name())
|
||||||
|
err := symlink(oldname, newname)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -201,6 +220,8 @@ func needsSyscallPackage(buildTags []string) bool {
|
|||||||
func pathsToOverride(needsSyscallPackage bool) map[string]bool {
|
func pathsToOverride(needsSyscallPackage bool) map[string]bool {
|
||||||
paths := map[string]bool{
|
paths := map[string]bool{
|
||||||
"/": true,
|
"/": true,
|
||||||
|
"crypto/": true,
|
||||||
|
"crypto/rand/": false,
|
||||||
"device/": false,
|
"device/": false,
|
||||||
"examples/": false,
|
"examples/": false,
|
||||||
"internal/": true,
|
"internal/": true,
|
||||||
|
|||||||
+5
-6
@@ -343,12 +343,11 @@ func (p *Package) Check() error {
|
|||||||
checker.Importer = p
|
checker.Importer = p
|
||||||
|
|
||||||
packageName := p.ImportPath
|
packageName := p.ImportPath
|
||||||
if p.Name == "main" {
|
if p == p.program.MainPkg() {
|
||||||
// The main package normally has a different import path, such as
|
if p.Name != "main" {
|
||||||
// "command-line-arguments" or "./testdata/cgo". Therefore, use the name
|
// Sanity check. Should not ever trigger.
|
||||||
// "main" in such a case: this package isn't imported from anywhere.
|
panic("expected main package to have name 'main'")
|
||||||
// This is safe as it isn't possible to import a package with the name
|
}
|
||||||
// "main".
|
|
||||||
packageName = "main"
|
packageName = "main"
|
||||||
}
|
}
|
||||||
typesPkg, err := checker.Check(packageName, p.program.fset, p.Files, &p.info)
|
typesPkg, err := checker.Check(packageName, p.program.fset, p.Files, &p.info)
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
@@ -95,12 +96,31 @@ func copyFile(src, dst string) error {
|
|||||||
|
|
||||||
// executeCommand is a simple wrapper to exec.Cmd
|
// executeCommand is a simple wrapper to exec.Cmd
|
||||||
func executeCommand(options *compileopts.Options, name string, arg ...string) *exec.Cmd {
|
func executeCommand(options *compileopts.Options, name string, arg ...string) *exec.Cmd {
|
||||||
if options.PrintCommands {
|
if options.PrintCommands != nil {
|
||||||
fmt.Printf("%s %s\n", name, strings.Join(arg, " "))
|
options.PrintCommands(name, arg...)
|
||||||
}
|
}
|
||||||
return exec.Command(name, arg...)
|
return exec.Command(name, arg...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// printCommand prints a command to stdout while formatting it like a real
|
||||||
|
// command (escaping characters etc). The resulting command should be easy to
|
||||||
|
// run directly in a shell, although it is not guaranteed to be a safe shell
|
||||||
|
// escape. That's not a problem as the primary use case is printing the command,
|
||||||
|
// not running it.
|
||||||
|
func printCommand(cmd string, args ...string) {
|
||||||
|
command := append([]string{cmd}, args...)
|
||||||
|
for i, arg := range command {
|
||||||
|
// Source: https://www.oreilly.com/library/view/learning-the-bash/1565923472/ch01s09.html
|
||||||
|
const specialChars = "~`#$&*()\\|[]{};'\"<>?! "
|
||||||
|
if strings.ContainsAny(arg, specialChars) {
|
||||||
|
// See: https://stackoverflow.com/questions/15783701/which-characters-need-to-be-escaped-when-using-bash
|
||||||
|
arg = "'" + strings.ReplaceAll(arg, `'`, `'\''`) + "'"
|
||||||
|
command[i] = arg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Fprintln(os.Stderr, strings.Join(command, " "))
|
||||||
|
}
|
||||||
|
|
||||||
// Build compiles and links the given package and writes it to outpath.
|
// Build compiles and links the given package and writes it to outpath.
|
||||||
func Build(pkgName, outpath string, options *compileopts.Options) error {
|
func Build(pkgName, outpath string, options *compileopts.Options) error {
|
||||||
config, err := builder.NewConfig(options)
|
config, err := builder.NewConfig(options)
|
||||||
@@ -145,7 +165,7 @@ func Test(pkgName string, options *compileopts.Options, testCompileOnly bool, ou
|
|||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var passed bool
|
passed := true
|
||||||
err = builder.Build(pkgName, outpath, config, func(result builder.BuildResult) error {
|
err = builder.Build(pkgName, outpath, config, func(result builder.BuildResult) error {
|
||||||
if testCompileOnly || outpath != "" {
|
if testCompileOnly || outpath != "" {
|
||||||
// Write test binary to the specified file name.
|
// Write test binary to the specified file name.
|
||||||
@@ -256,6 +276,8 @@ func Flash(pkgName, port string, options *compileopts.Options) error {
|
|||||||
fileExt = ".bin"
|
fileExt = ".bin"
|
||||||
case strings.Contains(config.Target.FlashCommand, "{uf2}"):
|
case strings.Contains(config.Target.FlashCommand, "{uf2}"):
|
||||||
fileExt = ".uf2"
|
fileExt = ".uf2"
|
||||||
|
case strings.Contains(config.Target.FlashCommand, "{zip}"):
|
||||||
|
fileExt = ".zip"
|
||||||
default:
|
default:
|
||||||
return errors.New("invalid target file - did you forget the {hex} token in the 'flash-command' section?")
|
return errors.New("invalid target file - did you forget the {hex} token in the 'flash-command' section?")
|
||||||
}
|
}
|
||||||
@@ -275,7 +297,7 @@ func Flash(pkgName, port string, options *compileopts.Options) error {
|
|||||||
return builder.Build(pkgName, fileExt, config, func(result builder.BuildResult) error {
|
return builder.Build(pkgName, fileExt, config, func(result builder.BuildResult) error {
|
||||||
// do we need port reset to put MCU into bootloader mode?
|
// do we need port reset to put MCU into bootloader mode?
|
||||||
if config.Target.PortReset == "true" && flashMethod != "openocd" {
|
if config.Target.PortReset == "true" && flashMethod != "openocd" {
|
||||||
port, err := getDefaultPort(strings.FieldsFunc(port, func(c rune) bool { return c == ',' }))
|
port, err := getDefaultPort(port, config.Target.SerialPort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -293,36 +315,36 @@ func Flash(pkgName, port string, options *compileopts.Options) error {
|
|||||||
case "", "command":
|
case "", "command":
|
||||||
// Create the command.
|
// Create the command.
|
||||||
flashCmd := config.Target.FlashCommand
|
flashCmd := config.Target.FlashCommand
|
||||||
fileToken := "{" + fileExt[1:] + "}"
|
flashCmdList, err := shlex.Split(flashCmd)
|
||||||
flashCmd = strings.ReplaceAll(flashCmd, fileToken, result.Binary)
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not parse flash command %#v: %w", flashCmd, err)
|
||||||
|
}
|
||||||
|
|
||||||
if strings.Contains(flashCmd, "{port}") {
|
if strings.Contains(flashCmd, "{port}") {
|
||||||
var err error
|
var err error
|
||||||
port, err = getDefaultPort(strings.FieldsFunc(port, func(c rune) bool { return c == ',' }))
|
port, err = getDefaultPort(port, config.Target.SerialPort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
flashCmd = strings.ReplaceAll(flashCmd, "{port}", port)
|
// Fill in fields in the command template.
|
||||||
|
fileToken := "{" + fileExt[1:] + "}"
|
||||||
// Execute the command.
|
for i, arg := range flashCmdList {
|
||||||
var cmd *exec.Cmd
|
arg = strings.ReplaceAll(arg, fileToken, result.Binary)
|
||||||
switch runtime.GOOS {
|
arg = strings.ReplaceAll(arg, "{port}", port)
|
||||||
case "windows":
|
flashCmdList[i] = arg
|
||||||
command := strings.Split(flashCmd, " ")
|
|
||||||
if len(command) < 2 {
|
|
||||||
return errors.New("invalid flash command")
|
|
||||||
}
|
|
||||||
cmd = executeCommand(config.Options, command[0], command[1:]...)
|
|
||||||
default:
|
|
||||||
cmd = executeCommand(config.Options, "/bin/sh", "-c", flashCmd)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Execute the command.
|
||||||
|
if len(flashCmdList) < 2 {
|
||||||
|
return fmt.Errorf("invalid flash command: %#v", flashCmd)
|
||||||
|
}
|
||||||
|
cmd := executeCommand(config.Options, flashCmdList[0], flashCmdList[1:]...)
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
cmd.Dir = goenv.Get("TINYGOROOT")
|
cmd.Dir = goenv.Get("TINYGOROOT")
|
||||||
err := cmd.Run()
|
err = cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &commandError{"failed to flash", result.Binary, err}
|
return &commandError{"failed to flash", result.Binary, err}
|
||||||
}
|
}
|
||||||
@@ -413,7 +435,7 @@ func FlashGDB(pkgName string, ocdOutput bool, options *compileopts.Options) erro
|
|||||||
case "native":
|
case "native":
|
||||||
// Run GDB directly.
|
// Run GDB directly.
|
||||||
case "openocd":
|
case "openocd":
|
||||||
gdbCommands = append(gdbCommands, "target remote :3333", "monitor halt", "load", "monitor reset halt")
|
gdbCommands = append(gdbCommands, "target extended-remote :3333", "monitor halt", "load", "monitor reset halt")
|
||||||
|
|
||||||
// We need a separate debugging daemon for on-chip debugging.
|
// We need a separate debugging daemon for on-chip debugging.
|
||||||
args, err := config.OpenOCDConfiguration()
|
args, err := config.OpenOCDConfiguration()
|
||||||
@@ -432,7 +454,7 @@ func FlashGDB(pkgName string, ocdOutput bool, options *compileopts.Options) erro
|
|||||||
daemon.Stderr = w
|
daemon.Stderr = w
|
||||||
}
|
}
|
||||||
case "jlink":
|
case "jlink":
|
||||||
gdbCommands = append(gdbCommands, "target remote :2331", "load", "monitor reset halt")
|
gdbCommands = append(gdbCommands, "target extended-remote :2331", "load", "monitor reset halt")
|
||||||
|
|
||||||
// We need a separate debugging daemon for on-chip debugging.
|
// We need a separate debugging daemon for on-chip debugging.
|
||||||
daemon = executeCommand(config.Options, "JLinkGDBServer", "-device", config.Target.JLinkDevice)
|
daemon = executeCommand(config.Options, "JLinkGDBServer", "-device", config.Target.JLinkDevice)
|
||||||
@@ -447,7 +469,7 @@ func FlashGDB(pkgName string, ocdOutput bool, options *compileopts.Options) erro
|
|||||||
daemon.Stderr = w
|
daemon.Stderr = w
|
||||||
}
|
}
|
||||||
case "qemu":
|
case "qemu":
|
||||||
gdbCommands = append(gdbCommands, "target remote :1234")
|
gdbCommands = append(gdbCommands, "target extended-remote :1234")
|
||||||
|
|
||||||
// Run in an emulator.
|
// Run in an emulator.
|
||||||
args := append(config.Target.Emulator[1:], result.Binary, "-s", "-S")
|
args := append(config.Target.Emulator[1:], result.Binary, "-s", "-S")
|
||||||
@@ -455,7 +477,7 @@ func FlashGDB(pkgName string, ocdOutput bool, options *compileopts.Options) erro
|
|||||||
daemon.Stdout = os.Stdout
|
daemon.Stdout = os.Stdout
|
||||||
daemon.Stderr = os.Stderr
|
daemon.Stderr = os.Stderr
|
||||||
case "qemu-user":
|
case "qemu-user":
|
||||||
gdbCommands = append(gdbCommands, "target remote :1234")
|
gdbCommands = append(gdbCommands, "target extended-remote :1234")
|
||||||
|
|
||||||
// Run in an emulator.
|
// Run in an emulator.
|
||||||
args := append(config.Target.Emulator[1:], "-g", "1234", result.Binary)
|
args := append(config.Target.Emulator[1:], "-g", "1234", result.Binary)
|
||||||
@@ -463,7 +485,7 @@ func FlashGDB(pkgName string, ocdOutput bool, options *compileopts.Options) erro
|
|||||||
daemon.Stdout = os.Stdout
|
daemon.Stdout = os.Stdout
|
||||||
daemon.Stderr = os.Stderr
|
daemon.Stderr = os.Stderr
|
||||||
case "mgba":
|
case "mgba":
|
||||||
gdbCommands = append(gdbCommands, "target remote :2345")
|
gdbCommands = append(gdbCommands, "target extended-remote :2345")
|
||||||
|
|
||||||
// Run in an emulator.
|
// Run in an emulator.
|
||||||
args := append(config.Target.Emulator[1:], result.Binary, "-g")
|
args := append(config.Target.Emulator[1:], result.Binary, "-g")
|
||||||
@@ -471,7 +493,7 @@ func FlashGDB(pkgName string, ocdOutput bool, options *compileopts.Options) erro
|
|||||||
daemon.Stdout = os.Stdout
|
daemon.Stdout = os.Stdout
|
||||||
daemon.Stderr = os.Stderr
|
daemon.Stderr = os.Stderr
|
||||||
case "simavr":
|
case "simavr":
|
||||||
gdbCommands = append(gdbCommands, "target remote :1234")
|
gdbCommands = append(gdbCommands, "target extended-remote :1234")
|
||||||
|
|
||||||
// Run in an emulator.
|
// Run in an emulator.
|
||||||
args := append(config.Target.Emulator[1:], "-g", result.Binary)
|
args := append(config.Target.Emulator[1:], "-g", result.Binary)
|
||||||
@@ -697,7 +719,8 @@ func windowsFindUSBDrive(volume string, options *compileopts.Options) (string, e
|
|||||||
}
|
}
|
||||||
|
|
||||||
// getDefaultPort returns the default serial port depending on the operating system.
|
// getDefaultPort returns the default serial port depending on the operating system.
|
||||||
func getDefaultPort(portCandidates []string) (port string, err error) {
|
func getDefaultPort(portFlag string, usbInterfaces []string) (port string, err error) {
|
||||||
|
portCandidates := strings.FieldsFunc(portFlag, func(c rune) bool { return c == ',' })
|
||||||
if len(portCandidates) == 1 {
|
if len(portCandidates) == 1 {
|
||||||
return portCandidates[0], nil
|
return portCandidates[0], nil
|
||||||
}
|
}
|
||||||
@@ -713,13 +736,70 @@ func getDefaultPort(portCandidates []string) (port string, err error) {
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, p := range portsList {
|
var preferredPortIDs [][2]uint16
|
||||||
if p.IsUSB {
|
for _, s := range usbInterfaces {
|
||||||
ports = append(ports, p.Name)
|
parts := strings.Split(s, ":")
|
||||||
|
if len(parts) != 3 || (parts[0] != "acm" && parts[0] == "usb") {
|
||||||
|
// acm and usb are the two types of serial ports recognized
|
||||||
|
// under Linux (ttyACM*, ttyUSB*). Other operating systems don't
|
||||||
|
// generally make this distinction. If this is not one of the
|
||||||
|
// given USB devices, don't try to parse the USB IDs.
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
vid, err := strconv.ParseUint(parts[1], 16, 16)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("could not parse USB vendor ID %q: %w", parts[1], err)
|
||||||
|
}
|
||||||
|
pid, err := strconv.ParseUint(parts[2], 16, 16)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("could not parse USB product ID %q: %w", parts[1], err)
|
||||||
|
}
|
||||||
|
preferredPortIDs = append(preferredPortIDs, [2]uint16{uint16(vid), uint16(pid)})
|
||||||
}
|
}
|
||||||
|
|
||||||
if ports == nil || len(ports) == 0 {
|
var primaryPorts []string // ports picked from preferred USB VID/PID
|
||||||
|
var secondaryPorts []string // other ports (as a fallback)
|
||||||
|
for _, p := range portsList {
|
||||||
|
if !p.IsUSB {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if p.VID != "" && p.PID != "" {
|
||||||
|
foundPort := false
|
||||||
|
vid, vidErr := strconv.ParseUint(p.VID, 16, 16)
|
||||||
|
pid, pidErr := strconv.ParseUint(p.PID, 16, 16)
|
||||||
|
if vidErr == nil && pidErr == nil {
|
||||||
|
for _, id := range preferredPortIDs {
|
||||||
|
if uint16(vid) == id[0] && uint16(pid) == id[1] {
|
||||||
|
primaryPorts = append(primaryPorts, p.Name)
|
||||||
|
foundPort = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if foundPort {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
secondaryPorts = append(secondaryPorts, p.Name)
|
||||||
|
}
|
||||||
|
if len(primaryPorts) == 1 {
|
||||||
|
// There is exactly one match in the set of preferred ports. Use
|
||||||
|
// this port, even if there may be others available. This allows
|
||||||
|
// flashing a specific board even if there are multiple available.
|
||||||
|
return primaryPorts[0], nil
|
||||||
|
} else if len(primaryPorts) > 1 {
|
||||||
|
// There are multiple preferred ports, probably because more than
|
||||||
|
// one device of the same type are connected (e.g. two Arduino
|
||||||
|
// Unos).
|
||||||
|
ports = primaryPorts
|
||||||
|
} else {
|
||||||
|
// No preferred ports found. Fall back to other serial ports
|
||||||
|
// available in the system.
|
||||||
|
ports = secondaryPorts
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(ports) == 0 {
|
||||||
// fallback
|
// fallback
|
||||||
switch runtime.GOOS {
|
switch runtime.GOOS {
|
||||||
case "darwin":
|
case "darwin":
|
||||||
@@ -929,6 +1009,7 @@ func main() {
|
|||||||
gc := flag.String("gc", "", "garbage collector to use (none, leaking, extalloc, conservative)")
|
gc := flag.String("gc", "", "garbage collector to use (none, leaking, extalloc, conservative)")
|
||||||
panicStrategy := flag.String("panic", "print", "panic strategy (print, trap)")
|
panicStrategy := flag.String("panic", "print", "panic strategy (print, trap)")
|
||||||
scheduler := flag.String("scheduler", "", "which scheduler to use (none, coroutines, tasks)")
|
scheduler := flag.String("scheduler", "", "which scheduler to use (none, coroutines, tasks)")
|
||||||
|
serial := flag.String("serial", "", "which serial output to use (none, uart, usb)")
|
||||||
printIR := flag.Bool("printir", false, "print LLVM IR")
|
printIR := flag.Bool("printir", false, "print LLVM IR")
|
||||||
dumpSSA := flag.Bool("dumpssa", false, "dump internal Go SSA")
|
dumpSSA := flag.Bool("dumpssa", false, "dump internal Go SSA")
|
||||||
verifyIR := flag.Bool("verifyir", false, "run extra verification steps on LLVM IR")
|
verifyIR := flag.Bool("verifyir", false, "run extra verification steps on LLVM IR")
|
||||||
@@ -938,7 +1019,7 @@ func main() {
|
|||||||
printStacks := flag.Bool("print-stacks", false, "print stack sizes of goroutines")
|
printStacks := flag.Bool("print-stacks", false, "print stack sizes of goroutines")
|
||||||
printAllocsString := flag.String("print-allocs", "", "regular expression of functions for which heap allocations should be printed")
|
printAllocsString := flag.String("print-allocs", "", "regular expression of functions for which heap allocations should be printed")
|
||||||
printCommands := flag.Bool("x", false, "Print commands")
|
printCommands := flag.Bool("x", false, "Print commands")
|
||||||
nodebug := flag.Bool("no-debug", false, "disable DWARF debug symbol generation")
|
nodebug := flag.Bool("no-debug", false, "strip debug information")
|
||||||
ocdCommandsString := flag.String("ocd-commands", "", "OpenOCD commands, overriding target spec (can specify multiple separated by commas)")
|
ocdCommandsString := flag.String("ocd-commands", "", "OpenOCD commands, overriding target spec (can specify multiple separated by commas)")
|
||||||
ocdOutput := flag.Bool("ocd-output", false, "print OCD daemon output during debug")
|
ocdOutput := flag.Bool("ocd-output", false, "print OCD daemon output during debug")
|
||||||
port := flag.String("port", "", "flash port (can specify multiple candidates separated by commas)")
|
port := flag.String("port", "", "flash port (can specify multiple candidates separated by commas)")
|
||||||
@@ -947,10 +1028,11 @@ func main() {
|
|||||||
wasmAbi := flag.String("wasm-abi", "", "WebAssembly ABI conventions: js (no i64 params) or generic")
|
wasmAbi := flag.String("wasm-abi", "", "WebAssembly ABI conventions: js (no i64 params) or generic")
|
||||||
llvmFeatures := flag.String("llvm-features", "", "comma separated LLVM features to enable")
|
llvmFeatures := flag.String("llvm-features", "", "comma separated LLVM features to enable")
|
||||||
|
|
||||||
var flagJSON, flagDeps *bool
|
var flagJSON, flagDeps, flagTest *bool
|
||||||
if command == "help" || command == "list" {
|
if command == "help" || command == "list" {
|
||||||
flagJSON = flag.Bool("json", false, "print data in JSON format")
|
flagJSON = flag.Bool("json", false, "print data in JSON format")
|
||||||
flagDeps = flag.Bool("deps", false, "")
|
flagDeps = flag.Bool("deps", false, "supply -deps flag to go list")
|
||||||
|
flagTest = flag.Bool("test", false, "supply -test flag to go list")
|
||||||
}
|
}
|
||||||
var outpath string
|
var outpath string
|
||||||
if command == "help" || command == "build" || command == "build-library" || command == "test" {
|
if command == "help" || command == "build" || command == "build-library" || command == "test" {
|
||||||
@@ -1000,6 +1082,7 @@ func main() {
|
|||||||
GC: *gc,
|
GC: *gc,
|
||||||
PanicStrategy: *panicStrategy,
|
PanicStrategy: *panicStrategy,
|
||||||
Scheduler: *scheduler,
|
Scheduler: *scheduler,
|
||||||
|
Serial: *serial,
|
||||||
PrintIR: *printIR,
|
PrintIR: *printIR,
|
||||||
DumpSSA: *dumpSSA,
|
DumpSSA: *dumpSSA,
|
||||||
VerifyIR: *verifyIR,
|
VerifyIR: *verifyIR,
|
||||||
@@ -1007,7 +1090,6 @@ func main() {
|
|||||||
PrintSizes: *printSize,
|
PrintSizes: *printSize,
|
||||||
PrintStacks: *printStacks,
|
PrintStacks: *printStacks,
|
||||||
PrintAllocs: printAllocs,
|
PrintAllocs: printAllocs,
|
||||||
PrintCommands: *printCommands,
|
|
||||||
Tags: *tags,
|
Tags: *tags,
|
||||||
GlobalValues: globalVarValues,
|
GlobalValues: globalVarValues,
|
||||||
WasmAbi: *wasmAbi,
|
WasmAbi: *wasmAbi,
|
||||||
@@ -1015,6 +1097,9 @@ func main() {
|
|||||||
OpenOCDCommands: ocdCommands,
|
OpenOCDCommands: ocdCommands,
|
||||||
LLVMFeatures: *llvmFeatures,
|
LLVMFeatures: *llvmFeatures,
|
||||||
}
|
}
|
||||||
|
if *printCommands {
|
||||||
|
options.PrintCommands = printCommand
|
||||||
|
}
|
||||||
|
|
||||||
os.Setenv("CC", "clang -target="+*target)
|
os.Setenv("CC", "clang -target="+*target)
|
||||||
|
|
||||||
@@ -1200,6 +1285,9 @@ func main() {
|
|||||||
if *flagDeps {
|
if *flagDeps {
|
||||||
extraArgs = append(extraArgs, "-deps")
|
extraArgs = append(extraArgs, "-deps")
|
||||||
}
|
}
|
||||||
|
if *flagTest {
|
||||||
|
extraArgs = append(extraArgs, "-test")
|
||||||
|
}
|
||||||
cmd, err := loader.List(config, extraArgs, flag.Args())
|
cmd, err := loader.List(config, extraArgs, flag.Args())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintln(os.Stderr, "failed to run `go list`:", err)
|
fmt.Fprintln(os.Stderr, "failed to run `go list`:", err)
|
||||||
|
|||||||
+14
-15
@@ -125,7 +125,7 @@ func TestCompiler(t *testing.T) {
|
|||||||
// Test with few optimizations enabled (no inlining, etc).
|
// Test with few optimizations enabled (no inlining, etc).
|
||||||
t.Run("opt=1", func(t *testing.T) {
|
t.Run("opt=1", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
runTestWithConfig("stdlib.go", "", t, &compileopts.Options{
|
runTestWithConfig("stdlib.go", "", t, compileopts.Options{
|
||||||
Opt: "1",
|
Opt: "1",
|
||||||
}, nil, nil)
|
}, nil, nil)
|
||||||
})
|
})
|
||||||
@@ -134,15 +134,14 @@ func TestCompiler(t *testing.T) {
|
|||||||
// TODO: fix this for stdlib.go, which currently fails.
|
// TODO: fix this for stdlib.go, which currently fails.
|
||||||
t.Run("opt=0", func(t *testing.T) {
|
t.Run("opt=0", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
runTestWithConfig("print.go", "", t, &compileopts.Options{
|
runTestWithConfig("print.go", "", t, compileopts.Options{
|
||||||
Opt: "0",
|
Opt: "0",
|
||||||
}, nil, nil)
|
}, nil, nil)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("ldflags", func(t *testing.T) {
|
t.Run("ldflags", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
runTestWithConfig("ldflags.go", "", t, &compileopts.Options{
|
runTestWithConfig("ldflags.go", "", t, compileopts.Options{
|
||||||
Opt: "z",
|
|
||||||
GlobalValues: map[string]map[string]string{
|
GlobalValues: map[string]map[string]string{
|
||||||
"main": {
|
"main": {
|
||||||
"someGlobal": "foobar",
|
"someGlobal": "foobar",
|
||||||
@@ -188,20 +187,20 @@ func runBuild(src, out string, opts *compileopts.Options) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runTest(name, target string, t *testing.T, cmdArgs, environmentVars []string) {
|
func runTest(name, target string, t *testing.T, cmdArgs, environmentVars []string) {
|
||||||
options := &compileopts.Options{
|
options := compileopts.Options{
|
||||||
Target: target,
|
Target: target,
|
||||||
Opt: "z",
|
|
||||||
PrintIR: false,
|
|
||||||
DumpSSA: false,
|
|
||||||
VerifyIR: true,
|
|
||||||
Debug: true,
|
|
||||||
PrintSizes: "",
|
|
||||||
WasmAbi: "",
|
|
||||||
}
|
}
|
||||||
runTestWithConfig(name, target, t, options, cmdArgs, environmentVars)
|
runTestWithConfig(name, target, t, options, cmdArgs, environmentVars)
|
||||||
}
|
}
|
||||||
|
|
||||||
func runTestWithConfig(name, target string, t *testing.T, options *compileopts.Options, cmdArgs, environmentVars []string) {
|
func runTestWithConfig(name, target string, t *testing.T, options compileopts.Options, cmdArgs, environmentVars []string) {
|
||||||
|
// Set default config.
|
||||||
|
options.Debug = true
|
||||||
|
options.VerifyIR = true
|
||||||
|
if options.Opt == "" {
|
||||||
|
options.Opt = "z"
|
||||||
|
}
|
||||||
|
|
||||||
// Get the expected output for this test.
|
// Get the expected output for this test.
|
||||||
// Note: not using filepath.Join as it strips the path separator at the end
|
// Note: not using filepath.Join as it strips the path separator at the end
|
||||||
// of the path.
|
// of the path.
|
||||||
@@ -230,7 +229,7 @@ func runTestWithConfig(name, target string, t *testing.T, options *compileopts.O
|
|||||||
|
|
||||||
// Build the test binary.
|
// Build the test binary.
|
||||||
binary := filepath.Join(tmpdir, "test")
|
binary := filepath.Join(tmpdir, "test")
|
||||||
err = runBuild("./"+path, binary, options)
|
err = runBuild("./"+path, binary, &options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
printCompilerError(t.Log, err)
|
printCompilerError(t.Log, err)
|
||||||
t.Fail()
|
t.Fail()
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
// Copyright 2010 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.
|
||||||
|
|
||||||
|
// Package rand implements a cryptographically secure
|
||||||
|
// random number generator.
|
||||||
|
package rand
|
||||||
|
|
||||||
|
import "io"
|
||||||
|
|
||||||
|
// Reader is a global, shared instance of a cryptographically
|
||||||
|
// secure random number generator.
|
||||||
|
var Reader io.Reader
|
||||||
|
|
||||||
|
// Read is a helper function that calls Reader.Read using io.ReadFull.
|
||||||
|
// On return, n == len(b) if and only if err == nil.
|
||||||
|
func Read(b []byte) (n int, err error) {
|
||||||
|
return io.ReadFull(Reader, b)
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
// +build darwin freebsd wasi
|
||||||
|
|
||||||
|
// This implementation of crypto/rand uses the getentropy system call (available
|
||||||
|
// on both MacOS and WASI) to generate random numbers.
|
||||||
|
|
||||||
|
package rand
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
var errReadFailed = errors.New("rand: could not read random bytes")
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
Reader = &reader{}
|
||||||
|
}
|
||||||
|
|
||||||
|
type reader struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *reader) Read(b []byte) (n int, err error) {
|
||||||
|
if len(b) != 0 {
|
||||||
|
if len(b) > 256 {
|
||||||
|
b = b[:256]
|
||||||
|
}
|
||||||
|
result := libc_getentropy(unsafe.Pointer(&b[0]), len(b))
|
||||||
|
if result < 0 {
|
||||||
|
// Maybe we should return a syscall.Errno here?
|
||||||
|
return 0, errReadFailed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return len(b), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// int getentropy(void *buf, size_t buflen);
|
||||||
|
//export getentropy
|
||||||
|
func libc_getentropy(buf unsafe.Pointer, buflen int) int
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
// +build linux,!baremetal,!wasi
|
||||||
|
|
||||||
|
// This implementation of crypto/rand uses the /dev/urandom pseudo-file to
|
||||||
|
// generate random numbers.
|
||||||
|
// TODO: convert to the getentropy or getrandom libc function on Linux once it
|
||||||
|
// is more widely supported.
|
||||||
|
|
||||||
|
package rand
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
Reader = &reader{}
|
||||||
|
}
|
||||||
|
|
||||||
|
type reader struct {
|
||||||
|
fd int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *reader) Read(b []byte) (n int, err error) {
|
||||||
|
if len(b) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open /dev/urandom first if needed.
|
||||||
|
if r.fd == 0 {
|
||||||
|
fd, err := syscall.Open("/dev/urandom", syscall.O_RDONLY, 0)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
r.fd = fd
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read from the file.
|
||||||
|
return syscall.Read(r.fd, b)
|
||||||
|
}
|
||||||
@@ -0,0 +1,143 @@
|
|||||||
|
// Copyright 2011 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.
|
||||||
|
|
||||||
|
package rand
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"math/big"
|
||||||
|
)
|
||||||
|
|
||||||
|
// smallPrimes is a list of small, prime numbers that allows us to rapidly
|
||||||
|
// exclude some fraction of composite candidates when searching for a random
|
||||||
|
// prime. This list is truncated at the point where smallPrimesProduct exceeds
|
||||||
|
// a uint64. It does not include two because we ensure that the candidates are
|
||||||
|
// odd by construction.
|
||||||
|
var smallPrimes = []uint8{
|
||||||
|
3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53,
|
||||||
|
}
|
||||||
|
|
||||||
|
// smallPrimesProduct is the product of the values in smallPrimes and allows us
|
||||||
|
// to reduce a candidate prime by this number and then determine whether it's
|
||||||
|
// coprime to all the elements of smallPrimes without further big.Int
|
||||||
|
// operations.
|
||||||
|
var smallPrimesProduct = new(big.Int).SetUint64(16294579238595022365)
|
||||||
|
|
||||||
|
// Prime returns a number, p, of the given size, such that p is prime
|
||||||
|
// with high probability.
|
||||||
|
// Prime will return error for any error returned by rand.Read or if bits < 2.
|
||||||
|
func Prime(rand io.Reader, bits int) (p *big.Int, err error) {
|
||||||
|
if bits < 2 {
|
||||||
|
err = errors.New("crypto/rand: prime size must be at least 2-bit")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
b := uint(bits % 8)
|
||||||
|
if b == 0 {
|
||||||
|
b = 8
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes := make([]byte, (bits+7)/8)
|
||||||
|
p = new(big.Int)
|
||||||
|
|
||||||
|
bigMod := new(big.Int)
|
||||||
|
|
||||||
|
for {
|
||||||
|
_, err = io.ReadFull(rand, bytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear bits in the first byte to make sure the candidate has a size <= bits.
|
||||||
|
bytes[0] &= uint8(int(1<<b) - 1)
|
||||||
|
// Don't let the value be too small, i.e, set the most significant two bits.
|
||||||
|
// Setting the top two bits, rather than just the top bit,
|
||||||
|
// means that when two of these values are multiplied together,
|
||||||
|
// the result isn't ever one bit short.
|
||||||
|
if b >= 2 {
|
||||||
|
bytes[0] |= 3 << (b - 2)
|
||||||
|
} else {
|
||||||
|
// Here b==1, because b cannot be zero.
|
||||||
|
bytes[0] |= 1
|
||||||
|
if len(bytes) > 1 {
|
||||||
|
bytes[1] |= 0x80
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Make the value odd since an even number this large certainly isn't prime.
|
||||||
|
bytes[len(bytes)-1] |= 1
|
||||||
|
|
||||||
|
p.SetBytes(bytes)
|
||||||
|
|
||||||
|
// Calculate the value mod the product of smallPrimes. If it's
|
||||||
|
// a multiple of any of these primes we add two until it isn't.
|
||||||
|
// The probability of overflowing is minimal and can be ignored
|
||||||
|
// because we still perform Miller-Rabin tests on the result.
|
||||||
|
bigMod.Mod(p, smallPrimesProduct)
|
||||||
|
mod := bigMod.Uint64()
|
||||||
|
|
||||||
|
NextDelta:
|
||||||
|
for delta := uint64(0); delta < 1<<20; delta += 2 {
|
||||||
|
m := mod + delta
|
||||||
|
for _, prime := range smallPrimes {
|
||||||
|
if m%uint64(prime) == 0 && (bits > 6 || m != uint64(prime)) {
|
||||||
|
continue NextDelta
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if delta > 0 {
|
||||||
|
bigMod.SetUint64(delta)
|
||||||
|
p.Add(p, bigMod)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// There is a tiny possibility that, by adding delta, we caused
|
||||||
|
// the number to be one bit too long. Thus we check BitLen
|
||||||
|
// here.
|
||||||
|
if p.ProbablyPrime(20) && p.BitLen() == bits {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int returns a uniform random value in [0, max). It panics if max <= 0.
|
||||||
|
func Int(rand io.Reader, max *big.Int) (n *big.Int, err error) {
|
||||||
|
if max.Sign() <= 0 {
|
||||||
|
panic("crypto/rand: argument to Int is <= 0")
|
||||||
|
}
|
||||||
|
n = new(big.Int)
|
||||||
|
n.Sub(max, n.SetUint64(1))
|
||||||
|
// bitLen is the maximum bit length needed to encode a value < max.
|
||||||
|
bitLen := n.BitLen()
|
||||||
|
if bitLen == 0 {
|
||||||
|
// the only valid result is 0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// k is the maximum byte length needed to encode a value < max.
|
||||||
|
k := (bitLen + 7) / 8
|
||||||
|
// b is the number of bits in the most significant byte of max-1.
|
||||||
|
b := uint(bitLen % 8)
|
||||||
|
if b == 0 {
|
||||||
|
b = 8
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes := make([]byte, k)
|
||||||
|
|
||||||
|
for {
|
||||||
|
_, err = io.ReadFull(rand, bytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear bits in the first byte to increase the probability
|
||||||
|
// that the candidate is < max.
|
||||||
|
bytes[0] &= uint8(int(1<<b) - 1)
|
||||||
|
|
||||||
|
n.SetBytes(bytes)
|
||||||
|
if n.Cmp(max) < 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/rand"
|
||||||
|
"runtime"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
ms := runtime.MemStats{}
|
||||||
|
|
||||||
|
for {
|
||||||
|
escapesToHeap()
|
||||||
|
runtime.ReadMemStats(&ms)
|
||||||
|
println("Heap before GC. Used: ", ms.HeapInuse, " Free: ", ms.HeapIdle, " Meta: ", ms.GCSys)
|
||||||
|
runtime.GC()
|
||||||
|
runtime.ReadMemStats(&ms)
|
||||||
|
println("Heap after GC. Used: ", ms.HeapInuse, " Free: ", ms.HeapIdle, " Meta: ", ms.GCSys)
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func escapesToHeap() {
|
||||||
|
n := rand.Intn(100)
|
||||||
|
println("Doing ", n, " iterations")
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
s := make([]byte, i)
|
||||||
|
_ = append(s, 42)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
// +build stm32
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "machine"
|
||||||
|
|
||||||
|
const (
|
||||||
|
buttonMode = machine.PinInputPulldown
|
||||||
|
buttonPinChange = machine.PinRising | machine.PinFalling
|
||||||
|
)
|
||||||
@@ -13,7 +13,7 @@ type Task struct {
|
|||||||
Ptr unsafe.Pointer
|
Ptr unsafe.Pointer
|
||||||
|
|
||||||
// Data is a field which can be used for storing state information.
|
// Data is a field which can be used for storing state information.
|
||||||
Data uint
|
Data uint64
|
||||||
|
|
||||||
// state is the underlying running state of the task.
|
// state is the underlying running state of the task.
|
||||||
state state
|
state state
|
||||||
|
|||||||
@@ -47,8 +47,6 @@ const (
|
|||||||
LED = D6
|
LED = D6
|
||||||
)
|
)
|
||||||
|
|
||||||
var Serial = USB
|
|
||||||
|
|
||||||
// USBCDC pins
|
// USBCDC pins
|
||||||
const (
|
const (
|
||||||
USBCDC_DM_PIN Pin = PA24
|
USBCDC_DM_PIN Pin = PA24
|
||||||
|
|||||||
@@ -35,8 +35,6 @@ const (
|
|||||||
LED3 Pin = PB03 // RX LED
|
LED3 Pin = PB03 // RX LED
|
||||||
)
|
)
|
||||||
|
|
||||||
var Serial = USB
|
|
||||||
|
|
||||||
// ADC pins
|
// ADC pins
|
||||||
const (
|
const (
|
||||||
AREF Pin = PA03
|
AREF Pin = PA03
|
||||||
|
|||||||
@@ -74,5 +74,3 @@ const (
|
|||||||
PB30 Pin = 62
|
PB30 Pin = 62
|
||||||
PB31 Pin = 63
|
PB31 Pin = 63
|
||||||
)
|
)
|
||||||
|
|
||||||
var Serial = USB
|
|
||||||
|
|||||||
@@ -15,8 +15,6 @@ const (
|
|||||||
BUTTON = PB31
|
BUTTON = PB31
|
||||||
)
|
)
|
||||||
|
|
||||||
var Serial = USB
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// https://ww1.microchip.com/downloads/en/DeviceDoc/70005321A.pdf
|
// https://ww1.microchip.com/downloads/en/DeviceDoc/70005321A.pdf
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,13 @@ const (
|
|||||||
LED = PC13
|
LED = PC13
|
||||||
)
|
)
|
||||||
|
|
||||||
var Serial = UART1
|
const (
|
||||||
|
// This board does not have a user button, so
|
||||||
|
// use first GPIO pin by default
|
||||||
|
BUTTON = PA0
|
||||||
|
)
|
||||||
|
|
||||||
|
var DefaultUART = UART1
|
||||||
|
|
||||||
// UART pins
|
// UART pins
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ const (
|
|||||||
const (
|
const (
|
||||||
LED = D13
|
LED = D13
|
||||||
NEOPIXELS = D8
|
NEOPIXELS = D8
|
||||||
|
WS2812 = D8
|
||||||
|
|
||||||
BUTTONA = D4
|
BUTTONA = D4
|
||||||
BUTTONB = D5
|
BUTTONB = D5
|
||||||
@@ -56,8 +57,6 @@ const (
|
|||||||
UART_RX_PIN = P0_30 // PORTB
|
UART_RX_PIN = P0_30 // PORTB
|
||||||
)
|
)
|
||||||
|
|
||||||
var Serial = USB
|
|
||||||
|
|
||||||
// I2C pins
|
// I2C pins
|
||||||
const (
|
const (
|
||||||
SDA_PIN = P0_05 // I2C0 external
|
SDA_PIN = P0_05 // I2C0 external
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ const (
|
|||||||
const (
|
const (
|
||||||
LED = D13
|
LED = D13
|
||||||
NEOPIXELS = D8
|
NEOPIXELS = D8
|
||||||
|
WS2812 = D8
|
||||||
|
|
||||||
BUTTONA = D4
|
BUTTONA = D4
|
||||||
BUTTONB = D5
|
BUTTONB = D5
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ const (
|
|||||||
LED1 = LED
|
LED1 = LED
|
||||||
LED2 = D43
|
LED2 = D43
|
||||||
NEOPIXEL = D18
|
NEOPIXEL = D18
|
||||||
|
WS2812 = D18
|
||||||
|
|
||||||
BUTTON_LEFT = D5
|
BUTTON_LEFT = D5
|
||||||
BUTTON_RIGHT = D11
|
BUTTON_RIGHT = D11
|
||||||
@@ -103,11 +104,6 @@ const (
|
|||||||
UART_TX_PIN = D1
|
UART_TX_PIN = D1
|
||||||
)
|
)
|
||||||
|
|
||||||
// Serial is the USB device
|
|
||||||
var (
|
|
||||||
Serial = USB
|
|
||||||
)
|
|
||||||
|
|
||||||
// I2C pins
|
// I2C pins
|
||||||
const (
|
const (
|
||||||
SDA_PIN = D20 // I2C0 external
|
SDA_PIN = D20 // I2C0 external
|
||||||
|
|||||||
@@ -68,8 +68,6 @@ const (
|
|||||||
ADC3 Pin = IO39
|
ADC3 Pin = IO39
|
||||||
)
|
)
|
||||||
|
|
||||||
var Serial = UART0
|
|
||||||
|
|
||||||
// UART0 pins
|
// UART0 pins
|
||||||
const (
|
const (
|
||||||
UART_TX_PIN = IO1
|
UART_TX_PIN = IO1
|
||||||
|
|||||||
@@ -44,10 +44,9 @@ const (
|
|||||||
const (
|
const (
|
||||||
LED = D13
|
LED = D13
|
||||||
NEOPIXELS = D8
|
NEOPIXELS = D8
|
||||||
|
WS2812 = D8
|
||||||
)
|
)
|
||||||
|
|
||||||
var Serial = USB
|
|
||||||
|
|
||||||
// USBCDC pins
|
// USBCDC pins
|
||||||
const (
|
const (
|
||||||
USBCDC_DM_PIN = PA24
|
USBCDC_DM_PIN = PA24
|
||||||
|
|||||||
@@ -36,11 +36,10 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
LED = D13
|
LED = D13
|
||||||
|
WS2812 = D8
|
||||||
)
|
)
|
||||||
|
|
||||||
var Serial = USB
|
|
||||||
|
|
||||||
// USBCDC pins
|
// USBCDC pins
|
||||||
const (
|
const (
|
||||||
USBCDC_DM_PIN = PA24
|
USBCDC_DM_PIN = PA24
|
||||||
|
|||||||
@@ -0,0 +1,105 @@
|
|||||||
|
// +build feather_nrf52840_sense
|
||||||
|
|
||||||
|
package machine
|
||||||
|
|
||||||
|
const HasLowFrequencyCrystal = true
|
||||||
|
|
||||||
|
// GPIO Pins
|
||||||
|
const (
|
||||||
|
D0 = P0_25 // UART TX
|
||||||
|
D1 = P0_24 // UART RX
|
||||||
|
D2 = P0_10 // NFC2
|
||||||
|
D3 = P1_11
|
||||||
|
D4 = P1_10 // LED2
|
||||||
|
D5 = P1_08
|
||||||
|
D6 = P0_07
|
||||||
|
D7 = P1_02 // Button
|
||||||
|
D8 = P0_16 // NeoPixel
|
||||||
|
D9 = P0_26
|
||||||
|
D10 = P0_27
|
||||||
|
D11 = P0_06
|
||||||
|
D12 = P0_08
|
||||||
|
D13 = P1_09 // LED1
|
||||||
|
D14 = P0_04 // A0
|
||||||
|
D15 = P0_05 // A1
|
||||||
|
D16 = P0_30 // A2
|
||||||
|
D17 = P0_28 // A3
|
||||||
|
D18 = P0_02 // A4
|
||||||
|
D19 = P0_03 // A5
|
||||||
|
D20 = P0_29 // Battery
|
||||||
|
D21 = P0_31 // AREF
|
||||||
|
D22 = P0_12 // I2C SDA
|
||||||
|
D23 = P0_11 // I2C SCL
|
||||||
|
D24 = P0_15 // SPI MISO
|
||||||
|
D25 = P0_13 // SPI MOSI
|
||||||
|
D26 = P0_14 // SPI SCK
|
||||||
|
D27 = P0_19 // QSPI CLK
|
||||||
|
D28 = P0_20 // QSPI CS
|
||||||
|
D29 = P0_17 // QSPI Data 0
|
||||||
|
D30 = P0_22 // QSPI Data 1
|
||||||
|
D31 = P0_23 // QSPI Data 2
|
||||||
|
D32 = P0_21 // QSPI Data 3
|
||||||
|
D33 = P0_09 // NFC1 (test point on bottom of board)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Analog Pins
|
||||||
|
const (
|
||||||
|
A0 = D14
|
||||||
|
A1 = D15
|
||||||
|
A2 = D16
|
||||||
|
A3 = D17
|
||||||
|
A4 = D18
|
||||||
|
A5 = D19
|
||||||
|
A6 = D20 // Battery
|
||||||
|
A7 = D21 // ARef
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
LED = D13
|
||||||
|
LED1 = LED
|
||||||
|
LED2 = D4
|
||||||
|
NEOPIXEL = D8
|
||||||
|
WS2812 = D8
|
||||||
|
BUTTON = D7
|
||||||
|
|
||||||
|
QSPI_SCK = D27
|
||||||
|
QSPI_CS = D28
|
||||||
|
QSPI_DATA0 = D29
|
||||||
|
QSPI_DATA1 = D30
|
||||||
|
QSPI_DATA2 = D31
|
||||||
|
QSPI_DATA3 = D32
|
||||||
|
)
|
||||||
|
|
||||||
|
// UART0 pins (logical UART1)
|
||||||
|
const (
|
||||||
|
UART_RX_PIN = D1
|
||||||
|
UART_TX_PIN = D0
|
||||||
|
)
|
||||||
|
|
||||||
|
// I2C pins
|
||||||
|
const (
|
||||||
|
SDA_PIN = D22 // I2C0 external
|
||||||
|
SCL_PIN = D23 // I2C0 external
|
||||||
|
)
|
||||||
|
|
||||||
|
// SPI pins
|
||||||
|
const (
|
||||||
|
SPI0_SCK_PIN = D26 // SCK
|
||||||
|
SPI0_SDO_PIN = D25 // SDO
|
||||||
|
SPI0_SDI_PIN = D24 // SDI
|
||||||
|
)
|
||||||
|
|
||||||
|
// USB CDC identifiers
|
||||||
|
const (
|
||||||
|
usb_STRING_PRODUCT = "Feather nRF52840 Express"
|
||||||
|
usb_STRING_MANUFACTURER = "Adafruit Industries LLC"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
usb_VID uint16 = 0x239A
|
||||||
|
usb_PID uint16 = 0x8088
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
DefaultUART = UART0
|
||||||
|
)
|
||||||
@@ -59,6 +59,7 @@ const (
|
|||||||
LED1 = LED
|
LED1 = LED
|
||||||
LED2 = D4
|
LED2 = D4
|
||||||
NEOPIXEL = D8
|
NEOPIXEL = D8
|
||||||
|
WS2812 = D8
|
||||||
BUTTON = D7
|
BUTTON = D7
|
||||||
|
|
||||||
QSPI_SCK = D27
|
QSPI_SCK = D27
|
||||||
@@ -71,13 +72,8 @@ const (
|
|||||||
|
|
||||||
// UART0 pins (logical UART1)
|
// UART0 pins (logical UART1)
|
||||||
const (
|
const (
|
||||||
UART_RX_PIN = D0
|
UART_RX_PIN = D1
|
||||||
UART_TX_PIN = D1
|
UART_TX_PIN = D0
|
||||||
)
|
|
||||||
|
|
||||||
// Serial is the USB device
|
|
||||||
var (
|
|
||||||
Serial = USB
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// I2C pins
|
// I2C pins
|
||||||
@@ -103,3 +99,7 @@ var (
|
|||||||
usb_VID uint16 = 0x239A
|
usb_VID uint16 = 0x239A
|
||||||
usb_PID uint16 = 0x802A
|
usb_PID uint16 = 0x802A
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
DefaultUART = UART0
|
||||||
|
)
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ const (
|
|||||||
LED_NEOPIXEL = D8
|
LED_NEOPIXEL = D8
|
||||||
LED_BUILTIN = LED_RED
|
LED_BUILTIN = LED_RED
|
||||||
LED = LED_BUILTIN
|
LED = LED_BUILTIN
|
||||||
|
WS2812 = D8
|
||||||
)
|
)
|
||||||
|
|
||||||
func initLED() {}
|
func initLED() {}
|
||||||
@@ -140,7 +141,7 @@ var (
|
|||||||
TxAltFuncSelector: AF7_USART1_2_3,
|
TxAltFuncSelector: AF7_USART1_2_3,
|
||||||
RxAltFuncSelector: AF7_USART1_2_3,
|
RxAltFuncSelector: AF7_USART1_2_3,
|
||||||
}
|
}
|
||||||
Serial = UART1
|
DefaultUART = UART1
|
||||||
)
|
)
|
||||||
|
|
||||||
func initUART() {
|
func initUART() {
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
// +build feather_rp2040
|
||||||
|
|
||||||
|
package machine
|
||||||
|
|
||||||
|
const (
|
||||||
|
LED = GPIO13
|
||||||
|
|
||||||
|
// Onboard crystal oscillator frequency, in MHz.
|
||||||
|
xoscFreq = 12 // MHz
|
||||||
|
)
|
||||||
|
|
||||||
|
// 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 = GPIO20 // 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
|
||||||
|
)
|
||||||
@@ -139,10 +139,9 @@ const (
|
|||||||
LED_RX = UART_RX_LED_PIN
|
LED_RX = UART_RX_LED_PIN
|
||||||
LED_TX = UART_TX_LED_PIN
|
LED_TX = UART_TX_LED_PIN
|
||||||
NEOPIXEL = NEOPIXEL_PIN
|
NEOPIXEL = NEOPIXEL_PIN
|
||||||
|
WS2812 = NEOPIXEL_PIN
|
||||||
)
|
)
|
||||||
|
|
||||||
var Serial = USB
|
|
||||||
|
|
||||||
// UART pins
|
// UART pins
|
||||||
const (
|
const (
|
||||||
UART1_RX_PIN = D0 // (PB25)
|
UART1_RX_PIN = D0 // (PB25)
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ const (
|
|||||||
LED_BLUE = P21
|
LED_BLUE = P21
|
||||||
)
|
)
|
||||||
|
|
||||||
var Serial = UART0
|
var DefaultUART = UART0
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// TODO: figure out the pin numbers for these.
|
// TODO: figure out the pin numbers for these.
|
||||||
|
|||||||
@@ -37,8 +37,6 @@ const (
|
|||||||
LED = D13
|
LED = D13
|
||||||
)
|
)
|
||||||
|
|
||||||
var Serial = USB
|
|
||||||
|
|
||||||
// USBCDC pins
|
// USBCDC pins
|
||||||
const (
|
const (
|
||||||
USBCDC_DM_PIN = PA24
|
USBCDC_DM_PIN = PA24
|
||||||
|
|||||||
@@ -70,11 +70,6 @@ const (
|
|||||||
UART_TX_PIN = D1
|
UART_TX_PIN = D1
|
||||||
)
|
)
|
||||||
|
|
||||||
// Serial is the USB device
|
|
||||||
var (
|
|
||||||
Serial = USB
|
|
||||||
)
|
|
||||||
|
|
||||||
// I2C pins
|
// I2C pins
|
||||||
const (
|
const (
|
||||||
SDA_PIN = D21 // I2C0 external
|
SDA_PIN = D21 // I2C0 external
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ const (
|
|||||||
I2C0_SDA_PIN = PA10
|
I2C0_SDA_PIN = PA10
|
||||||
)
|
)
|
||||||
|
|
||||||
var Serial = UART0
|
var DefaultUART = UART0
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ const (
|
|||||||
LED_BLUE = D14
|
LED_BLUE = D14
|
||||||
)
|
)
|
||||||
|
|
||||||
var Serial = UART0
|
var DefaultUART = UART0
|
||||||
|
|
||||||
// Default pins for UARTHS.
|
// Default pins for UARTHS.
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ const (
|
|||||||
const (
|
const (
|
||||||
LED = D13
|
LED = D13
|
||||||
NEOPIXEL = D4
|
NEOPIXEL = D4
|
||||||
|
WS2812 = D4
|
||||||
)
|
)
|
||||||
|
|
||||||
// Button pins
|
// Button pins
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
|
|
||||||
// UART on the MatrixPortal M4
|
// UART on the MatrixPortal M4
|
||||||
var (
|
var (
|
||||||
|
Serial = UART1
|
||||||
UART1 = &_UART1
|
UART1 = &_UART1
|
||||||
_UART1 = UART{
|
_UART1 = UART{
|
||||||
Buffer: NewRingBuffer(),
|
Buffer: NewRingBuffer(),
|
||||||
|
|||||||
@@ -37,11 +37,10 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
LED = D13
|
LED = D13
|
||||||
|
WS2812 = D40
|
||||||
)
|
)
|
||||||
|
|
||||||
var Serial = USB
|
|
||||||
|
|
||||||
// USBCDC pins
|
// USBCDC pins
|
||||||
const (
|
const (
|
||||||
USBCDC_DM_PIN = PA24
|
USBCDC_DM_PIN = PA24
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ const (
|
|||||||
BUTTONB Pin = P11
|
BUTTONB Pin = P11
|
||||||
)
|
)
|
||||||
|
|
||||||
var Serial = UART0
|
var DefaultUART = UART0
|
||||||
|
|
||||||
// UART pins
|
// UART pins
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ const (
|
|||||||
BUTTONB Pin = 26
|
BUTTONB Pin = 26
|
||||||
)
|
)
|
||||||
|
|
||||||
var Serial = UART0
|
var DefaultUART = UART0
|
||||||
|
|
||||||
// UART pins
|
// UART pins
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -0,0 +1,95 @@
|
|||||||
|
// +build nano_33_ble
|
||||||
|
|
||||||
|
// This contains the pin mappings for the Arduino Nano 33 BLE [Sense] boards.
|
||||||
|
//
|
||||||
|
// Flashing the board requires special version of bossac.
|
||||||
|
//
|
||||||
|
// This executable can be obtained two ways:
|
||||||
|
// 1) In Arduino IDE, install support for the board ("Arduino Mbed OS Nano Boards")
|
||||||
|
// Search for "tools/bossac/1.9.1-arduino2/bossac" in Arduino IDEs directory
|
||||||
|
// 2) Download https://downloads.arduino.cc/packages/package_index.json
|
||||||
|
// Search for "bossac-1.9.1-arduino2" in that file
|
||||||
|
// Download tarball for your OS and unpack it
|
||||||
|
//
|
||||||
|
// Once you have the executable, make it accessible in your PATH as "bossac_arduino2".
|
||||||
|
//
|
||||||
|
// It is possible to replace original bossac with this new one (this only adds support for nrf chip).
|
||||||
|
// In that case make "bossac_arduino2" symlink on it, for the board target to be able to find it.
|
||||||
|
//
|
||||||
|
// For more information, see:
|
||||||
|
// - https://store.arduino.cc/arduino-nano-33-ble
|
||||||
|
// - https://store.arduino.cc/arduino-nano-33-ble-sense
|
||||||
|
//
|
||||||
|
package machine
|
||||||
|
|
||||||
|
const HasLowFrequencyCrystal = true
|
||||||
|
|
||||||
|
// Digital Pins
|
||||||
|
const (
|
||||||
|
D2 Pin = P1_11
|
||||||
|
D3 Pin = P1_12
|
||||||
|
D4 Pin = P1_15
|
||||||
|
D5 Pin = P1_13
|
||||||
|
D6 Pin = P1_14
|
||||||
|
D7 Pin = P0_23
|
||||||
|
D8 Pin = P0_21
|
||||||
|
D9 Pin = P0_27
|
||||||
|
D10 Pin = P1_02
|
||||||
|
D11 Pin = P1_01
|
||||||
|
D12 Pin = P1_08
|
||||||
|
D13 Pin = P0_13
|
||||||
|
)
|
||||||
|
|
||||||
|
// Analog pins
|
||||||
|
const (
|
||||||
|
A0 Pin = P0_04
|
||||||
|
A1 Pin = P0_05
|
||||||
|
A2 Pin = P0_30
|
||||||
|
A3 Pin = P0_29
|
||||||
|
A4 Pin = P0_31
|
||||||
|
A5 Pin = P0_02
|
||||||
|
A6 Pin = P0_28
|
||||||
|
A7 Pin = P0_03
|
||||||
|
)
|
||||||
|
|
||||||
|
// Onboard LEDs
|
||||||
|
const (
|
||||||
|
LED = LED_BUILTIN
|
||||||
|
LED1 = LED_RED
|
||||||
|
LED2 = LED_GREEN
|
||||||
|
LED3 = LED_BLUE
|
||||||
|
LED_BUILTIN = P0_13
|
||||||
|
LED_RED = P0_24
|
||||||
|
LED_GREEN = P0_16
|
||||||
|
LED_BLUE = P0_06
|
||||||
|
)
|
||||||
|
|
||||||
|
// UART0 pins
|
||||||
|
const (
|
||||||
|
UART_RX_PIN = P1_10
|
||||||
|
UART_TX_PIN = P1_03
|
||||||
|
)
|
||||||
|
|
||||||
|
// I2C pins
|
||||||
|
const (
|
||||||
|
SDA_PIN = P0_31
|
||||||
|
SCL_PIN = P0_02
|
||||||
|
)
|
||||||
|
|
||||||
|
// SPI pins
|
||||||
|
const (
|
||||||
|
SPI0_SCK_PIN = P0_13
|
||||||
|
SPI0_SDO_PIN = P1_01
|
||||||
|
SPI0_SDI_PIN = P1_08
|
||||||
|
)
|
||||||
|
|
||||||
|
// USB CDC identifiers
|
||||||
|
const (
|
||||||
|
usb_STRING_PRODUCT = "Nano 33 BLE"
|
||||||
|
usb_STRING_MANUFACTURER = "Arduino"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
usb_VID uint16 = 0x2341
|
||||||
|
usb_PID uint16 = 0x805a
|
||||||
|
)
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
// +build nano_rp2040
|
||||||
|
|
||||||
|
// This contains the pin mappings for the Arduino Nano RP2040 Connect board.
|
||||||
|
//
|
||||||
|
// Sometimes the board is not detected even when the board is connected to your computer.
|
||||||
|
// To solve this, place a jumper wire between the REC and GND pins, then connect the board to your computer.
|
||||||
|
//
|
||||||
|
// For more information, see: https://store.arduino.cc/nano-rp2040-connect
|
||||||
|
// Also
|
||||||
|
// - Datasheets: https://docs.arduino.cc/hardware/nano-rp2040-connect
|
||||||
|
// - Nano RP2040 Connect technical reference: https://docs.arduino.cc/tutorials/nano-rp2040-connect/rp2040-01-technical-reference
|
||||||
|
//
|
||||||
|
package machine
|
||||||
|
|
||||||
|
// Digital Pins
|
||||||
|
const (
|
||||||
|
D2 Pin = GPIO25
|
||||||
|
D3 Pin = GPIO15
|
||||||
|
D4 Pin = GPIO16
|
||||||
|
D5 Pin = GPIO17
|
||||||
|
D6 Pin = GPIO18
|
||||||
|
D7 Pin = GPIO19
|
||||||
|
D8 Pin = GPIO20
|
||||||
|
D9 Pin = GPIO21
|
||||||
|
D10 Pin = GPIO5
|
||||||
|
D11 Pin = GPIO7
|
||||||
|
D12 Pin = GPIO4
|
||||||
|
D13 Pin = GPIO6
|
||||||
|
D14 Pin = GPIO26
|
||||||
|
D15 Pin = GPIO27
|
||||||
|
D16 Pin = GPIO28
|
||||||
|
D17 Pin = GPIO29
|
||||||
|
D18 Pin = GPIO12
|
||||||
|
D19 Pin = GPIO13
|
||||||
|
)
|
||||||
|
|
||||||
|
// Analog pins
|
||||||
|
const (
|
||||||
|
A0 Pin = ADC0
|
||||||
|
A1 Pin = ADC1
|
||||||
|
A2 Pin = ADC2
|
||||||
|
A3 Pin = ADC3
|
||||||
|
)
|
||||||
|
|
||||||
|
// Onboard LED
|
||||||
|
const (
|
||||||
|
LED = GPIO6
|
||||||
|
)
|
||||||
|
|
||||||
|
// I2C pins
|
||||||
|
const (
|
||||||
|
SDA_PIN Pin = GPIO12
|
||||||
|
SCL_PIN Pin = GPIO13
|
||||||
|
)
|
||||||
|
|
||||||
|
// SPI pins. SPI1 not available on Nano RP2040 Connect.
|
||||||
|
const (
|
||||||
|
SPI0_SCK_PIN Pin = GPIO6
|
||||||
|
SPI0_SDO_PIN Pin = GPIO7
|
||||||
|
SPI0_SDI_PIN Pin = GPIO4
|
||||||
|
|
||||||
|
// GPIO22 does not have SPI functionality so we set it to avoid interfering with NINA.
|
||||||
|
SPI1_SCK_PIN Pin = GPIO22
|
||||||
|
SPI1_SDO_PIN Pin = GPIO22
|
||||||
|
SPI1_SDI_PIN Pin = GPIO22
|
||||||
|
)
|
||||||
|
|
||||||
|
// NINA-W102 Pins
|
||||||
|
const (
|
||||||
|
NINA_SCK Pin = GPIO14
|
||||||
|
NINA_SDO Pin = GPIO11
|
||||||
|
NINA_SDI Pin = GPIO8
|
||||||
|
|
||||||
|
NINA_CS Pin = GPIO9
|
||||||
|
NINA_ACK Pin = GPIO10
|
||||||
|
NINA_GPIO0 Pin = GPIO0
|
||||||
|
NINA_RESETN Pin = GPIO3
|
||||||
|
|
||||||
|
NINA_TX Pin = GPIO9
|
||||||
|
NINA_RX Pin = GPIO8
|
||||||
|
)
|
||||||
|
|
||||||
|
// Onboard crystal oscillator frequency, in MHz.
|
||||||
|
const (
|
||||||
|
xoscFreq = 12 // MHz
|
||||||
|
)
|
||||||
|
|
||||||
|
// USB CDC identifiers
|
||||||
|
// https://github.com/arduino/ArduinoCore-mbed/blob/master/variants/NANO_RP2040_CONNECT/pins_arduino.h
|
||||||
|
const (
|
||||||
|
usb_STRING_PRODUCT = "Nano RP2040 Connect"
|
||||||
|
usb_STRING_MANUFACTURER = "Arduino"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
usb_VID uint16 = 0x2341
|
||||||
|
usb_PID uint16 = 0x005e
|
||||||
|
)
|
||||||
@@ -54,11 +54,6 @@ const (
|
|||||||
UART_TX_PIN = P0_08
|
UART_TX_PIN = P0_08
|
||||||
)
|
)
|
||||||
|
|
||||||
// Serial is the USB device
|
|
||||||
var (
|
|
||||||
Serial = USB
|
|
||||||
)
|
|
||||||
|
|
||||||
// I2C pins
|
// I2C pins
|
||||||
const (
|
const (
|
||||||
SDA_PIN = P0_17 // I2C0 external
|
SDA_PIN = P0_17 // I2C0 external
|
||||||
|
|||||||
@@ -20,8 +20,6 @@ const (
|
|||||||
// Onboard blue LED (on the AI-Thinker module).
|
// Onboard blue LED (on the AI-Thinker module).
|
||||||
const LED = D4
|
const LED = D4
|
||||||
|
|
||||||
var Serial = UART0
|
|
||||||
|
|
||||||
// SPI pins
|
// SPI pins
|
||||||
const (
|
const (
|
||||||
SPI0_SCK_PIN = D5
|
SPI0_SCK_PIN = D5
|
||||||
|
|||||||
@@ -23,9 +23,6 @@ const (
|
|||||||
UART_RX_PIN Pin = NoPin
|
UART_RX_PIN Pin = NoPin
|
||||||
)
|
)
|
||||||
|
|
||||||
// Serial is the USB device
|
|
||||||
var Serial = USB
|
|
||||||
|
|
||||||
// I2C pins (unused)
|
// I2C pins (unused)
|
||||||
const (
|
const (
|
||||||
SDA_PIN = NoPin
|
SDA_PIN = NoPin
|
||||||
|
|||||||
@@ -18,9 +18,6 @@ const (
|
|||||||
UART_RX_PIN Pin = 19
|
UART_RX_PIN Pin = 19
|
||||||
)
|
)
|
||||||
|
|
||||||
// Serial is the USB device
|
|
||||||
var Serial = USB
|
|
||||||
|
|
||||||
// I2C pins (unused)
|
// I2C pins (unused)
|
||||||
const (
|
const (
|
||||||
SDA_PIN = NoPin
|
SDA_PIN = NoPin
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ var (
|
|||||||
Buffer: NewRingBuffer(),
|
Buffer: NewRingBuffer(),
|
||||||
Bus: stm32.USART2,
|
Bus: stm32.USART2,
|
||||||
}
|
}
|
||||||
Serial = UART2
|
DefaultUART = UART2
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ var (
|
|||||||
TxAltFuncSelector: UART_ALT_FN,
|
TxAltFuncSelector: UART_ALT_FN,
|
||||||
RxAltFuncSelector: UART_ALT_FN,
|
RxAltFuncSelector: UART_ALT_FN,
|
||||||
}
|
}
|
||||||
Serial = UART1
|
DefaultUART = UART1
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|||||||
@@ -13,6 +13,12 @@ const (
|
|||||||
LED_GREEN = PB3
|
LED_GREEN = PB3
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// This board does not have a user button, so
|
||||||
|
// use first GPIO pin by default
|
||||||
|
BUTTON = PA0
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Arduino Pins
|
// Arduino Pins
|
||||||
A0 = PA0 // ADC_IN0
|
A0 = PA0 // ADC_IN0
|
||||||
@@ -70,7 +76,7 @@ var (
|
|||||||
TxAltFuncSelector: 4,
|
TxAltFuncSelector: 4,
|
||||||
RxAltFuncSelector: 4,
|
RxAltFuncSelector: 4,
|
||||||
}
|
}
|
||||||
Serial = UART1
|
DefaultUART = UART1
|
||||||
|
|
||||||
// I2C1 is documented, alias to I2C0 as well
|
// I2C1 is documented, alias to I2C0 as well
|
||||||
I2C1 = &I2C{
|
I2C1 = &I2C{
|
||||||
|
|||||||
@@ -13,6 +13,12 @@ const (
|
|||||||
LED_GREEN = PB3
|
LED_GREEN = PB3
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// This board does not have a user button, so
|
||||||
|
// use first GPIO pin by default
|
||||||
|
BUTTON = PA0
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Arduino Pins
|
// Arduino Pins
|
||||||
A0 = PA0
|
A0 = PA0
|
||||||
@@ -72,7 +78,7 @@ var (
|
|||||||
TxAltFuncSelector: 7,
|
TxAltFuncSelector: 7,
|
||||||
RxAltFuncSelector: 3,
|
RxAltFuncSelector: 3,
|
||||||
}
|
}
|
||||||
Serial = UART1
|
DefaultUART = UART1
|
||||||
|
|
||||||
// I2C1 is documented, alias to I2C0 as well
|
// I2C1 is documented, alias to I2C0 as well
|
||||||
I2C1 = &I2C{
|
I2C1 = &I2C{
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ var (
|
|||||||
TxAltFuncSelector: UART_ALT_FN,
|
TxAltFuncSelector: UART_ALT_FN,
|
||||||
RxAltFuncSelector: UART_ALT_FN,
|
RxAltFuncSelector: UART_ALT_FN,
|
||||||
}
|
}
|
||||||
Serial = UART1
|
DefaultUART = UART1
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ const (
|
|||||||
|
|
||||||
// UART
|
// UART
|
||||||
var (
|
var (
|
||||||
Serial = UART0
|
DefaultUART = UART0
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ const (
|
|||||||
|
|
||||||
// UART
|
// UART
|
||||||
var (
|
var (
|
||||||
Serial = UART0
|
DefaultUART = UART0
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ const (
|
|||||||
|
|
||||||
// UART
|
// UART
|
||||||
var (
|
var (
|
||||||
Serial = UART0
|
DefaultUART = UART0
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ const (
|
|||||||
LED_BLUE Pin = 23
|
LED_BLUE Pin = 23
|
||||||
)
|
)
|
||||||
|
|
||||||
var Serial = UART0
|
var DefaultUART = UART0
|
||||||
|
|
||||||
// UART pins
|
// UART pins
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ const (
|
|||||||
BUTTON4 Pin = 16
|
BUTTON4 Pin = 16
|
||||||
)
|
)
|
||||||
|
|
||||||
var Serial = UART0
|
var DefaultUART = UART0
|
||||||
|
|
||||||
// UART pins for NRF52840-DK
|
// UART pins for NRF52840-DK
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ const (
|
|||||||
BUTTON4 Pin = 25
|
BUTTON4 Pin = 25
|
||||||
)
|
)
|
||||||
|
|
||||||
var Serial = UART0
|
var DefaultUART = UART0
|
||||||
|
|
||||||
// UART pins
|
// UART pins
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -34,11 +34,6 @@ const (
|
|||||||
UART_RX_PIN Pin = NoPin
|
UART_RX_PIN Pin = NoPin
|
||||||
)
|
)
|
||||||
|
|
||||||
// Serial is the USB device
|
|
||||||
var (
|
|
||||||
Serial = USB
|
|
||||||
)
|
|
||||||
|
|
||||||
// I2C pins (unused)
|
// I2C pins (unused)
|
||||||
const (
|
const (
|
||||||
SDA_PIN = NoPin
|
SDA_PIN = NoPin
|
||||||
|
|||||||
+44
-31
@@ -4,40 +4,53 @@ package machine
|
|||||||
|
|
||||||
// GPIO pins
|
// GPIO pins
|
||||||
const (
|
const (
|
||||||
GP0 Pin = 0
|
GP0 Pin = GPIO0
|
||||||
GP1 Pin = 1
|
GP1 Pin = GPIO1
|
||||||
GP2 Pin = 2
|
GP2 Pin = GPIO2
|
||||||
GP3 Pin = 3
|
GP3 Pin = GPIO3
|
||||||
GP4 Pin = 4
|
GP4 Pin = GPIO4
|
||||||
GP5 Pin = 5
|
GP5 Pin = GPIO5
|
||||||
GP6 Pin = 6
|
GP6 Pin = GPIO6
|
||||||
GP7 Pin = 7
|
GP7 Pin = GPIO7
|
||||||
GP8 Pin = 8
|
GP8 Pin = GPIO8
|
||||||
GP9 Pin = 9
|
GP9 Pin = GPIO9
|
||||||
GP10 Pin = 10
|
GP10 Pin = GPIO10
|
||||||
GP11 Pin = 11
|
GP11 Pin = GPIO11
|
||||||
GP12 Pin = 12
|
GP12 Pin = GPIO12
|
||||||
GP13 Pin = 13
|
GP13 Pin = GPIO13
|
||||||
GP14 Pin = 14
|
GP14 Pin = GPIO14
|
||||||
GP15 Pin = 15
|
GP15 Pin = GPIO15
|
||||||
GP16 Pin = 16
|
GP16 Pin = GPIO16
|
||||||
GP17 Pin = 17
|
GP17 Pin = GPIO17
|
||||||
GP18 Pin = 18
|
GP18 Pin = GPIO18
|
||||||
GP19 Pin = 19
|
GP19 Pin = GPIO19
|
||||||
GP20 Pin = 20
|
GP20 Pin = GPIO20
|
||||||
GP21 Pin = 21
|
GP21 Pin = GPIO21
|
||||||
GP22 Pin = 22
|
GP22 Pin = GPIO22
|
||||||
GP23 Pin = 23
|
GP26 Pin = GPIO26
|
||||||
GP24 Pin = 24
|
GP27 Pin = GPIO27
|
||||||
GP25 Pin = 25
|
GP28 Pin = GPIO28
|
||||||
GP26 Pin = 26
|
|
||||||
GP27 Pin = 27
|
|
||||||
GP28 Pin = 28
|
|
||||||
GP29 Pin = 29
|
|
||||||
|
|
||||||
// Onboard LED
|
// Onboard LED
|
||||||
LED Pin = GP25
|
LED Pin = GPIO25
|
||||||
|
|
||||||
// Onboard crystal oscillator frequency, in MHz.
|
// Onboard crystal oscillator frequency, in MHz.
|
||||||
xoscFreq = 12 // MHz
|
xoscFreq = 12 // MHz
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// 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
|
||||||
|
)
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ const (
|
|||||||
LED3 = LCD_BACKLIGHT_LOW
|
LED3 = LCD_BACKLIGHT_LOW
|
||||||
)
|
)
|
||||||
|
|
||||||
var Serial = UART0
|
var DefaultUART = UART0
|
||||||
|
|
||||||
// UART pins for PineTime. Note that RX is set to NoPin as RXD is not listed in
|
// UART pins for PineTime. Note that RX is set to NoPin as RXD is not listed in
|
||||||
// the PineTime schematic 1.0:
|
// the PineTime schematic 1.0:
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ const (
|
|||||||
const (
|
const (
|
||||||
LED = D13
|
LED = D13
|
||||||
NEOPIXELS = D8
|
NEOPIXELS = D8
|
||||||
|
WS2812 = D8
|
||||||
|
|
||||||
LIGHTSENSOR = A7
|
LIGHTSENSOR = A7
|
||||||
|
|
||||||
@@ -66,8 +67,6 @@ const (
|
|||||||
BUTTON_B_MASK = 128
|
BUTTON_B_MASK = 128
|
||||||
)
|
)
|
||||||
|
|
||||||
var Serial = USB
|
|
||||||
|
|
||||||
// USBCDC pins
|
// USBCDC pins
|
||||||
const (
|
const (
|
||||||
USBCDC_DM_PIN = PA24
|
USBCDC_DM_PIN = PA24
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ const (
|
|||||||
const (
|
const (
|
||||||
LED = D13
|
LED = D13
|
||||||
NEOPIXELS = D8
|
NEOPIXELS = D8
|
||||||
|
WS2812 = D8
|
||||||
|
|
||||||
SD_CS = D7
|
SD_CS = D7
|
||||||
|
|
||||||
@@ -69,8 +70,6 @@ const (
|
|||||||
BUTTON_B_MASK = 128
|
BUTTON_B_MASK = 128
|
||||||
)
|
)
|
||||||
|
|
||||||
var Serial = USB
|
|
||||||
|
|
||||||
// USBCDC pins
|
// USBCDC pins
|
||||||
const (
|
const (
|
||||||
USBCDC_DM_PIN = PA24
|
USBCDC_DM_PIN = PA24
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ const (
|
|||||||
TFT_WR = D26
|
TFT_WR = D26
|
||||||
|
|
||||||
NEOPIXEL = D2
|
NEOPIXEL = D2
|
||||||
|
WS2812 = D2
|
||||||
SPK_SD = D50
|
SPK_SD = D50
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -94,8 +95,6 @@ const (
|
|||||||
LED = D13
|
LED = D13
|
||||||
)
|
)
|
||||||
|
|
||||||
var Serial = USB
|
|
||||||
|
|
||||||
// USBCDC pins
|
// USBCDC pins
|
||||||
const (
|
const (
|
||||||
USBCDC_DM_PIN = PA24
|
USBCDC_DM_PIN = PA24
|
||||||
|
|||||||
@@ -42,7 +42,9 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
LED = D13
|
NEOPIXELS = D11
|
||||||
|
WS2812 = D11
|
||||||
|
NEOPIXELS_POWER = D12
|
||||||
)
|
)
|
||||||
|
|
||||||
// USBCDC pins
|
// USBCDC pins
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ const (
|
|||||||
BUTTON Pin = 7
|
BUTTON Pin = 7
|
||||||
)
|
)
|
||||||
|
|
||||||
var Serial = UART0
|
var DefaultUART = UART0
|
||||||
|
|
||||||
// UART pins
|
// UART pins
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -20,6 +20,10 @@ const (
|
|||||||
LED_BLUE = PD15
|
LED_BLUE = PD15
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
BUTTON = PA0
|
||||||
|
)
|
||||||
|
|
||||||
// UART pins
|
// UART pins
|
||||||
const (
|
const (
|
||||||
UART_TX_PIN = PA2
|
UART_TX_PIN = PA2
|
||||||
@@ -34,7 +38,7 @@ var (
|
|||||||
TxAltFuncSelector: AF7_USART1_2_3,
|
TxAltFuncSelector: AF7_USART1_2_3,
|
||||||
RxAltFuncSelector: AF7_USART1_2_3,
|
RxAltFuncSelector: AF7_USART1_2_3,
|
||||||
}
|
}
|
||||||
Serial = UART1
|
DefaultUART = UART1
|
||||||
)
|
)
|
||||||
|
|
||||||
// set up RX IRQ handler. Follow similar pattern for other UARTx instances
|
// set up RX IRQ handler. Follow similar pattern for other UARTx instances
|
||||||
|
|||||||
@@ -87,6 +87,8 @@ var (
|
|||||||
TeensyUART5 = UART4
|
TeensyUART5 = UART4
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var DefaultUART = UART0
|
||||||
|
|
||||||
const (
|
const (
|
||||||
defaultUART0RX = D00
|
defaultUART0RX = D00
|
||||||
defaultUART0TX = D01
|
defaultUART0TX = D01
|
||||||
|
|||||||
@@ -146,9 +146,9 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
Serial = UART1
|
DefaultUART = UART1
|
||||||
UART1 = &_UART1
|
UART1 = &_UART1
|
||||||
_UART1 = UART{
|
_UART1 = UART{
|
||||||
Bus: nxp.LPUART6,
|
Bus: nxp.LPUART6,
|
||||||
Buffer: NewRingBuffer(),
|
Buffer: NewRingBuffer(),
|
||||||
txBuffer: NewRingBuffer(),
|
txBuffer: NewRingBuffer(),
|
||||||
|
|||||||
@@ -325,8 +325,6 @@ const (
|
|||||||
OUTPUT_CTR_3V3 = PC15
|
OUTPUT_CTR_3V3 = PC15
|
||||||
)
|
)
|
||||||
|
|
||||||
var Serial = USB
|
|
||||||
|
|
||||||
// USBCDC pins
|
// USBCDC pins
|
||||||
const (
|
const (
|
||||||
USBCDC_DM_PIN = PIN_USB_DM
|
USBCDC_DM_PIN = PIN_USB_DM
|
||||||
|
|||||||
@@ -27,4 +27,4 @@ const (
|
|||||||
|
|
||||||
const HasLowFrequencyCrystal = true
|
const HasLowFrequencyCrystal = true
|
||||||
|
|
||||||
var Serial = UART0
|
var DefaultUART = UART0
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ func (i2c *I2C) readByte() byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Always use UART0 as the serial output.
|
// Always use UART0 as the serial output.
|
||||||
var Serial = UART0
|
var DefaultUART = UART0
|
||||||
|
|
||||||
// UART
|
// UART
|
||||||
var (
|
var (
|
||||||
|
|||||||
@@ -251,6 +251,8 @@ func (p Pin) mux() *volatile.Register32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var DefaultUART = UART0
|
||||||
|
|
||||||
var (
|
var (
|
||||||
UART0 = &_UART0
|
UART0 = &_UART0
|
||||||
_UART0 = UART{Bus: esp.UART0, Buffer: NewRingBuffer()}
|
_UART0 = UART{Bus: esp.UART0, Buffer: NewRingBuffer()}
|
||||||
|
|||||||
@@ -139,6 +139,8 @@ func (p Pin) PortMaskClear() (*uint32, uint32) {
|
|||||||
return &esp.GPIO.GPIO_OUT_W1TC.Reg, 1 << p
|
return &esp.GPIO.GPIO_OUT_W1TC.Reg, 1 << p
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var DefaultUART = UART0
|
||||||
|
|
||||||
// UART0 is a hardware UART that supports both TX and RX.
|
// UART0 is a hardware UART that supports both TX and RX.
|
||||||
var UART0 = &_UART0
|
var UART0 = &_UART0
|
||||||
var _UART0 = UART{Buffer: NewRingBuffer()}
|
var _UART0 = UART{Buffer: NewRingBuffer()}
|
||||||
|
|||||||
@@ -11,6 +11,12 @@ var (
|
|||||||
USB = &UART{100}
|
USB = &UART{100}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// The Serial port always points to the default UART in a simulated environment.
|
||||||
|
//
|
||||||
|
// TODO: perhaps this should be a special serial object that outputs via WASI
|
||||||
|
// stdout calls.
|
||||||
|
var Serial = UART0
|
||||||
|
|
||||||
const (
|
const (
|
||||||
PinInput PinMode = iota
|
PinInput PinMode = iota
|
||||||
PinOutput
|
PinOutput
|
||||||
@@ -118,12 +124,6 @@ type UART struct {
|
|||||||
Bus uint8
|
Bus uint8
|
||||||
}
|
}
|
||||||
|
|
||||||
type UARTConfig struct {
|
|
||||||
BaudRate uint32
|
|
||||||
TX Pin
|
|
||||||
RX Pin
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configure the UART.
|
// Configure the UART.
|
||||||
func (uart *UART) Configure(config UARTConfig) {
|
func (uart *UART) Configure(config UARTConfig) {
|
||||||
uartConfigure(uart.Bus, config.TX, config.RX)
|
uartConfigure(uart.Bus, config.TX, config.RX)
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user