Compare commits

..

56 Commits

Author SHA1 Message Date
Ayke van Laethem 3b68f8f16a machine: hide internal pin modes
Many pin modes are only for peripherals like SPI and PWM. Do not make
these part of the public API: the public API is the Configure method on
the peripheral, not the PinMode constant.
2022-09-26 18:27:55 +02:00
Damian Gryski fca2de21b1 runtime: make gc and scheduler asserts settable with build tags 2022-09-25 16:47:07 +02:00
Ayke van Laethem 107b1c2906 machine: do not expose RESET_MAGIC_VALUE
This is a constant for internal use only, but was (unintentionally?)
exported. In addition, it doesn't follow the Go naming convention.
This change simply renames the constant so that it is unexported.
2022-09-25 12:38:12 +02:00
deadprogram 2409bbef69 build: set circleci resource class to large for CI build
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-09-25 10:08:10 +02:00
Ayke van Laethem 8b078a9e8f machine: remove level triggered pin interrupts
This removes level-triggered interrupts.

While working on https://github.com/tinygo-org/tinygo/pull/3170, I found
these level triggered interrupt constants. Apart from them being
inconsistent with each other (PinLowLevel vs PinLevelLow) I don't think
they are actually used anywhere. In addition, I removed the
PinNoInterrupt constant on the esp32c3. This makes the esp32c3 pass the
tests in #3170.

I looked into level-triggered interrupts and I really couldn't find a
good justification for them:

  - They were added to the esp32c3 and the rp2040 together with other
    pin interrupt types, meaning they were probably just added because
    the chip supports the feature and not because they were actually
    needed.
  - Level interrupts aren't supported in TinyGo for any other chip, and
    I haven't seen anybody ask for this feature.
  - They aren't supported in the nrf series chips _at all_, and with a
    quick search I found only very little demand for them in general.
  - I tried to see whether there is any good use case for them, but I
    couldn't really find one (where an edge triggered interrupt wouldn't
    work just as well). If there is one where level triggered interrupts
    are a real advantage over edge triggered interrupts, please let me
    know.

Of course, we shouldn't remove a feature lightly. But in this case, I
can't think of an advantage of having this feature. I can think of
downsides: more maintenance and having to specify their behavior in the
machine package documentation.
In general, I would like to keep the machine package clean and only
support things that have a proven use case.
2022-09-24 22:58:22 +02:00
sago35 9e24441978 main: allow setting the baud rate for serial monitors (#3190)
* main: allow setting the baud rate for serial monitors with default baudrate of 115200 bps
2022-09-24 19:09:41 +02:00
Ayke van Laethem 1e6c14b3e4 ci: build TinyGo using Go 1.19
We've supported Go 1.19 for a while now, let's actually use it in CI.
2022-09-24 13:22:38 +02:00
Crypt Keeper 25f6be1488 build: makes CI choose latest Go 1.18.x (#3143)
* build: makes CI choose latest Go 1.18.x
2022-09-24 10:14:18 +02:00
Ayke van Laethem 9a9106a297 esp32c3: remove unused UARTStopBits constants 2022-09-21 18:16:29 +02:00
Ayke van Laethem a68f7e4ce3 nrf: add ReadTemperature method
Similar to the rp2040, the nrf has an on-board temperature sensor.

The main reason why I added this function was to show how this new API
is more general and can be used on multiple chips.
2022-09-21 08:26:56 +02:00
Ayke van Laethem 70b3ece6ec rp2040: add machine.ReadTemperature
Replace ADCChannel.ReadTemperature() with a simple ReadTemperature
function.

Not all chips will have a temperature sensor that is read by sampling an
ADC channel. The replacement ReadTemperature is simpler and more generic
to other chip families.

This breaks chips that were relying on the previous ReadTemperature
method. I hope it won't break a lot of existing code. If it does, a
fallback can be added.
2022-09-21 08:26:56 +02:00
Ayke van Laethem 86ea216e7d machine: move SPI Tx function into separate file
This makes the code a bit cleaner because ErrTxInvalidSliceSize isn't
redefined in every file that uses SPI and Mode0/Mode1/Mode2/Mode3 is
defined for every target that uses SPI.
2022-09-21 06:52:42 +02:00
Ayke van Laethem 5a92c35536 main: restore support for flashing Espressif chips
This reverts commit 303410d3fc and also
removes the unnecessary fallback.
2022-09-20 23:03:07 +02:00
Ayke van Laethem 7513fa2c96 machine: add KHz, MHz, GHz constants, deprecate TWI_FREQ_* constants
There are two main issues with these constants:

  * They don't follow the Go naming convention.
  * They call themselves "TWI", while it makes a lot more sense to refer
    to the actual name which is I2C (or I²C).

I have not removed them but just deprecated them. Perhaps we can remove
them when we move towards version 1.0.
2022-09-20 21:00:17 +02:00
Ayke van Laethem bc946f346d machine: rename PinInputPullUp/PinInputPullDown
Some targets used capital PullUp/PullDown, while the documented standard
is Pullup/Pulldown. This commit fixes this mismatch, while preserving
compatibility with aliases that are marked deprecated.
2022-09-20 05:45:53 +02:00
Ayke van Laethem 6e6666519c go mod tidy 2022-09-19 20:14:09 +02:00
Ayke van Laethem cecae8084c nrf52840: do not export DFU_MAGIC_* constants
These constants are for internal use only, so should not have been
exported. In addition, they didn't follow the Go naming convention
before this change.
2022-09-19 07:41:46 +02:00
Ayke van Laethem 9720ccacbb machine: improve UARTParity slightly
There are only 3 possible values, so a uint8 seems more appropriate.
Also, there is no reason to use specific numbers over a simple
enumeration.
2022-09-18 21:30:30 +02:00
Damian Gryski a5aa777c7b src/runtime: add a few more docs about the garbage collector 2022-09-18 15:19:11 +02:00
sago35 aca1ad187d targets: remove usbpid of bootloader
For more information, see
https://github.com/tinygo-org/tinygo/pull/3168
2022-09-17 11:00:31 +02:00
sago35 5a41ed6329 xiao-ble: fix usbpid 2022-09-17 07:25:41 +02:00
Ayke van Laethem 91e9c84d85 nrf: make GetRNG available to all chips
All nrf chips have a cryptographically secure RNG on board. Therefore,
I've made the code more portable so that it works on all nrf chips.

I did remove a number of exported functions. I am of the opinion that
these should only be made available once we have an agreed upon API for
multiple chips. People who want to have greater control over the RNG
should use the device/nrf package directly instead.

I have also changed the behavior to always enable digital error
correction. Enabling it seems like a more conservative (and secure)
default to me. Again, people who would like to have it disabled can use
the device/nrf package directly.
2022-09-17 06:08:54 +02:00
sago35 4af530f238 wioterminal: remove serial-port setting of bootloader 2022-09-16 20:12:47 +02:00
Ayke van Laethem d3863f337d rp2040: do not use GetRNG in crypto/rand
The crypto/rand package is used for sensitive cryptographic operations.
Do not use the rp2040 RNG for this purpose, because it's not strong
enough for cryptography.

I think it is _possible_ to make use of the RP2040 RNG to create
cryptographically secure pseudo-random numbers, but it needs some
entropy calculation and secure hashing (blake2s or so) to make them
truly unpredictable.
2022-09-16 14:48:41 +02:00
Ayke van Laethem 5551ec7a1e cgo: implement support for static functions 2022-09-16 14:05:17 +02:00
Ayke van Laethem 91104b2f27 runtime: ensure some headroom for the GC to run
The GC was originally designed for systems with a fixed amount of
memory, like baremetal systems. Therefore, it just used what it could
and ran a GC cycle when out of memory.

Other systems (like Linux or WebAssembly) are different. In those
systems, it is possible to grow the amount of memory on demand. But the
GC only actually grew the heap when it was really out of memory, not
when it was getting very close to being out of memory.

This patch fixes this by ensuring there is at least 33% headroom for the
GC. This means that programs can allocate around 50% more than what was
live in the last GC cycle. It should fix a performance cliff when a
program is almost, but not entirely, out of memory and the GC has to run
almost every heap allocation.
2022-09-16 11:11:50 +02:00
sago35 80f38e8449 main: add serial port monitoring functionality
Co-authored-by: Ayke <aykevanlaethem@gmail.com>
2022-09-16 09:28:03 +02:00
Adrian Cole 22893c5180 wasm: documents memory constants
This documents memory constants. Somewhere, we should document what the
default memory size is (seems 2 pages so 128KB), as that determines the
initial heap size (which is a portion of that).

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-09-16 07:32:43 +02:00
Ayke van Laethem 9e4e182615 interp: fix reading from external global
This fixes https://github.com/tinygo-org/tinygo/issues/3020.
2022-09-15 19:07:04 +02:00
Ayke van Laethem 5f96d2b784 all: add flag for setting the goroutine stack size
This is helpful in some cases where the default stack size isn't big
enough.
2022-09-15 12:43:51 +02:00
Ayke van Laethem bd1d93b705 go mod tidy 2022-09-15 12:43:51 +02:00
Anuraag Agrawal 03d1c44265 wasm,wasi: make sure buffers returned by malloc are not freed until f… (#3148)
* wasm,wasi: make sure buffers returned by malloc are not freed until free is called
2022-09-15 09:14:39 +02:00
Adrian Cole dc0346d968 wasi: adds more details about why wasmtime flags are added
Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-09-14 19:52:04 +02:00
Ayke van Laethem dadae95448 ci: use the Go Alpine image for building the release binary
This fixes https://github.com/tinygo-org/tinygo/issues/3146 by using a
prebuilt Docker image. I don't remember why I used `setup-go` but
probably to make it faster (setup-go usually uses cached binaries).
2022-09-14 15:43:14 +02:00
sago35 f5fc2fc072 main: add support for stlink-dap programmer 2022-09-14 14:58:31 +02:00
Matt Schultz 4ba76a5df9 machine/nrf52840: implement RNG peripheral operation 2022-09-12 09:54:51 +02:00
deadprogram ea1e08f53f machine/rp2040: implement semi-random RNG based on ROSC based on pico-sdk
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-09-10 10:47:48 +02:00
Adrian Cole bba0dc9575 build: uses setup-go@v3 to simplify cache config
This updates to setup-go@v3 which is the only updated version (v2 last
updated in feb), and employs its cache to simplify workflow
configuration.

Notably, we can't do this for Alpine until #3146

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-09-09 21:48:51 +02:00
Isaac Rodman 617c7586fe Remove unconnected simple LED pin from qtpy-rp2040 2022-09-09 11:05:12 +02:00
Isaac Rodman 7366d5e185 Set default-stack-size to 4096, and remove NEOPIXELS pluralization for qtpy-rp2040 2022-09-09 11:05:12 +02:00
Adrian Cole 96e3ecd949 build: updates to actions/cache@v3
v2 has bugs and hasn't had a release since last November.

See https://github.com/actions/cache/releases

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-09-08 16:27:40 +02:00
Ayke van Laethem 8bbfb1ee68 wasm: do not allow undefined symbols
--allow-undefined can be a problem: it allows compiling code that will
fail when loaded. This change makes sure that if some symbols are
undefined, they are reported as an error by the linker.

Previously, people could get away with importing a function that was not
defined, like this:

    func add(int a, int b) int

    func test() {
        println(add(3, 5))
    }

This was always unintended but mostly worked. With this change, it isn't
possible anymore. Now every function needs to be marked with //export
explicitly:

    //export add
    func add(int a, int b) int

    func test() {
        println(add(3, 5))
    }

As before, functions will be placed in the `env` module with the name
set from the `//export` tag. This can be overridden with
`//go:import-module`:

    //go:import-module math
    //export add
    func add(int a, int b) int

    func test() {
        println(add(3, 5))
    }

For the syscall/js package, I needed to give a list of symbols that are
undefined. This list is based on the JavaScript functions defined in
targets/wasm_exec.js.
2022-09-08 08:25:27 +02:00
Adrian Cole 07cdcc61f7 examples: adds summary of wasm examples and fixes callback bug
This adds a summary of each wasm example, as before it was a bit unclear
how to do so. This also fixes the callback example which was broken.

Fixes #2568

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-09-07 13:31:21 +02:00
Ayke van Laethem 4ca9b34133 machine: add PWM peripheral comments to pins
These comments will be used in a change to the tinygo.org documentation.
2022-09-05 18:56:34 +02:00
Patricio Whittingslow d5e4b16911 add github.com/soypat/mu8 to corpus.yaml 2022-09-04 09:42:49 +02:00
sago35 fd05254683 Update compileopts/target.go
Co-authored-by: Ayke <aykevanlaethem@gmail.com>
2022-09-03 11:50:41 +02:00
sago35 c579e7e509 Update compileopts/target.go
Co-authored-by: Ayke <aykevanlaethem@gmail.com>
2022-09-03 11:50:41 +02:00
sago35 d463528a72 smoketest: add test to run tinygo targets 2022-09-03 11:50:41 +02:00
sago35 49b0086f8f main: improve error handling when loading target/*.json 2022-09-03 11:50:41 +02:00
Yurii Soldak d7814ff50b targets: fix build tag duplicates
and add missing targets to smoke test
2022-09-03 08:31:27 +02:00
Ayke van Laethem 02160aa8d8 windows: run more tests where supported
I found that some packages do in fact run on Windows, so I've added them
where possible. I've also updated the description of which packages fail
tests and why.
2022-09-02 20:04:28 +02:00
Ayke van Laethem c199dd03c7 windows: save and restore xmm registers when switching goroutines
This is required according to the Windows x64 calling convention:
https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170#callercallee-saved-registers
We didn't do this, and this didn't appear to cause any problems. But we
should do it anyway for correctness.
2022-09-02 18:47:00 +02:00
Ayke van Laethem 472aecf07a targets: remove hifive1-qemu target
This target was added purely for running tests, and it is currently
unused. When I try to use it, it causes runtime exceptions.
The replacement riscv-qemu is much better behaved.

This doesn't drop support for any actual hardware, the HiFive 1 B will
remain supported.
2022-09-02 16:35:05 +02:00
Isaac Rodman 09350e5719 Add qtpy-rp2040 to TinyGo v0.25.0 2022-09-02 15:06:37 +02:00
Tim Schaub 623dd6a815 sync: implement map.LoadAndDelete 2022-09-02 11:48:01 +02:00
Joe Shaw e09bd5abb3 runtime/pprof, runtime/trace: stub some additional functions
These are necessary to import some parts of the net/http package.
2022-09-02 10:37:50 +02:00
158 changed files with 1529 additions and 916 deletions
+1 -10
View File
@@ -118,13 +118,7 @@ jobs:
steps: steps:
- test-linux: - test-linux:
llvm: "14" llvm: "14"
test-llvm14-go119: resource_class: large
docker:
- image: golang:1.19beta1-buster
steps:
- test-linux:
llvm: "14"
fmt-check: false
workflows: workflows:
test-all: test-all:
@@ -132,6 +126,3 @@ workflows:
# This tests our lowest supported versions of Go and LLVM, to make sure at # This tests our lowest supported versions of Go and LLVM, to make sure at
# least the smoke tests still pass. # least the smoke tests still pass.
- test-llvm14-go118 - test-llvm14-go118
# This tests a beta version of Go. It should be removed once regular
# release builds are built using this version.
- test-llvm14-go119
+12 -17
View File
@@ -16,10 +16,6 @@ jobs:
name: build-macos name: build-macos
runs-on: macos-11 runs-on: macos-11
steps: steps:
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: '1.18.1'
- name: Install Dependencies - name: Install Dependencies
shell: bash shell: bash
run: | run: |
@@ -35,8 +31,13 @@ jobs:
uses: actions/checkout@v2 uses: actions/checkout@v2
with: with:
submodules: true submodules: true
- name: Install Go
uses: actions/setup-go@v3
with:
go-version: '1.19'
cache: true
- name: Cache LLVM source - name: Cache LLVM source
uses: actions/cache@v2 uses: actions/cache@v3
id: cache-llvm-source id: cache-llvm-source
with: with:
key: llvm-source-14-macos-v1 key: llvm-source-14-macos-v1
@@ -50,7 +51,7 @@ jobs:
if: steps.cache-llvm-source.outputs.cache-hit != 'true' if: steps.cache-llvm-source.outputs.cache-hit != 'true'
run: make llvm-source run: make llvm-source
- name: Cache LLVM build - name: Cache LLVM build
uses: actions/cache@v2 uses: actions/cache@v3
id: cache-llvm-build id: cache-llvm-build
with: with:
key: llvm-build-14-macos-v1 key: llvm-build-14-macos-v1
@@ -68,7 +69,7 @@ jobs:
make llvm-build make llvm-build
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \; find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
- name: Cache wasi-libc sysroot - name: Cache wasi-libc sysroot
uses: actions/cache@v2 uses: actions/cache@v3
id: cache-wasi-libc id: cache-wasi-libc
with: with:
key: wasi-libc-sysroot-v4 key: wasi-libc-sysroot-v4
@@ -104,23 +105,17 @@ jobs:
name: homebrew-install name: homebrew-install
runs-on: macos-latest runs-on: macos-latest
steps: steps:
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: '1.18'
- name: Install LLVM - name: Install LLVM
shell: bash shell: bash
run: | run: |
HOMEBREW_NO_AUTO_UPDATE=1 brew install llvm@14 HOMEBREW_NO_AUTO_UPDATE=1 brew install llvm@14
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Cache Go - name: Install Go
uses: actions/cache@v2 uses: actions/setup-go@v3
with: with:
key: go-cache-macos-homebrew-v1-${{ hashFiles('go.mod') }} go-version: '1.19'
path: | cache: true
~/Library/Caches/go-build
~/go/pkg/mod
- name: Build TinyGo - name: Build TinyGo
run: go install run: go install
- name: Check binary - name: Check binary
+30 -52
View File
@@ -18,14 +18,13 @@ jobs:
# statically linked binary. # statically linked binary.
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: container:
image: alpine:3.16 image: golang:1.19-alpine
steps: steps:
- name: Install apk dependencies - name: Install apk dependencies
# tar: needed for actions/cache@v2 # tar: needed for actions/cache@v3
# git+openssh: needed for checkout (I think?) # git+openssh: needed for checkout (I think?)
# gcompat: needed for go binary
# ruby: needed to install fpm # ruby: needed to install fpm
run: apk add tar git openssh gcompat make g++ ruby run: apk add tar git openssh make g++ ruby
- name: Work around CVE-2022-24765 - name: Work around CVE-2022-24765
# We're not on a multi-user machine, so this is safe. # We're not on a multi-user machine, so this is safe.
run: git config --global --add safe.directory "$GITHUB_WORKSPACE" run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
@@ -33,19 +32,15 @@ jobs:
uses: actions/checkout@v2 uses: actions/checkout@v2
with: with:
submodules: true submodules: true
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: '1.18.1'
- name: Cache Go - name: Cache Go
uses: actions/cache@v2 uses: actions/cache@v3
with: with:
key: go-cache-linux-alpine-v1-${{ hashFiles('go.mod') }} key: go-cache-linux-alpine-v1-${{ hashFiles('go.mod') }}
path: | path: |
~/.cache/go-build ~/.cache/go-build
~/go/pkg/mod ~/go/pkg/mod
- name: Cache LLVM source - name: Cache LLVM source
uses: actions/cache@v2 uses: actions/cache@v3
id: cache-llvm-source id: cache-llvm-source
with: with:
key: llvm-source-14-linux-alpine-v1 key: llvm-source-14-linux-alpine-v1
@@ -59,7 +54,7 @@ jobs:
if: steps.cache-llvm-source.outputs.cache-hit != 'true' if: steps.cache-llvm-source.outputs.cache-hit != 'true'
run: make llvm-source run: make llvm-source
- name: Cache LLVM build - name: Cache LLVM build
uses: actions/cache@v2 uses: actions/cache@v3
id: cache-llvm-build id: cache-llvm-build
with: with:
key: llvm-build-14-linux-alpine-v1 key: llvm-build-14-linux-alpine-v1
@@ -77,7 +72,7 @@ jobs:
# Remove unnecessary object files (to reduce cache size). # Remove unnecessary object files (to reduce cache size).
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \; find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
- name: Cache Binaryen - name: Cache Binaryen
uses: actions/cache@v2 uses: actions/cache@v3
id: cache-binaryen id: cache-binaryen
with: with:
key: binaryen-linux-alpine-v1 key: binaryen-linux-alpine-v1
@@ -88,7 +83,7 @@ jobs:
apk add cmake samurai python3 apk add cmake samurai python3
make binaryen STATIC=1 make binaryen STATIC=1
- name: Cache wasi-libc - name: Cache wasi-libc
uses: actions/cache@v2 uses: actions/cache@v3
id: cache-wasi-libc id: cache-wasi-libc
with: with:
key: wasi-libc-sysroot-linux-alpine-v1 key: wasi-libc-sysroot-linux-alpine-v1
@@ -121,9 +116,10 @@ jobs:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Install Go - name: Install Go
uses: actions/setup-go@v2 uses: actions/setup-go@v3
with: with:
go-version: '1.18.1' go-version: '1.19'
cache: true
- name: Install wasmtime - name: Install wasmtime
run: | run: |
curl https://wasmtime.dev/install.sh -sSf | bash curl https://wasmtime.dev/install.sh -sSf | bash
@@ -173,9 +169,10 @@ jobs:
simavr \ simavr \
ninja-build ninja-build
- name: Install Go - name: Install Go
uses: actions/setup-go@v2 uses: actions/setup-go@v3
with: with:
go-version: '1.18.1' go-version: '1.19'
cache: true
- name: Install Node.js - name: Install Node.js
uses: actions/setup-node@v2 uses: actions/setup-node@v2
with: with:
@@ -184,15 +181,8 @@ jobs:
run: | run: |
curl https://wasmtime.dev/install.sh -sSf | bash curl https://wasmtime.dev/install.sh -sSf | bash
echo "$HOME/.wasmtime/bin" >> $GITHUB_PATH echo "$HOME/.wasmtime/bin" >> $GITHUB_PATH
- name: Cache Go
uses: actions/cache@v2
with:
key: go-cache-linux-asserts-v1-${{ hashFiles('go.mod') }}
path: |
~/.cache/go-build
~/go/pkg/mod
- name: Cache LLVM source - name: Cache LLVM source
uses: actions/cache@v2 uses: actions/cache@v3
id: cache-llvm-source id: cache-llvm-source
with: with:
key: llvm-source-14-linux-asserts-v2 key: llvm-source-14-linux-asserts-v2
@@ -206,7 +196,7 @@ jobs:
if: steps.cache-llvm-source.outputs.cache-hit != 'true' if: steps.cache-llvm-source.outputs.cache-hit != 'true'
run: make llvm-source run: make llvm-source
- name: Cache LLVM build - name: Cache LLVM build
uses: actions/cache@v2 uses: actions/cache@v3
id: cache-llvm-build id: cache-llvm-build
with: with:
key: llvm-build-14-linux-asserts-v1 key: llvm-build-14-linux-asserts-v1
@@ -222,7 +212,7 @@ jobs:
# Remove unnecessary object files (to reduce cache size). # Remove unnecessary object files (to reduce cache size).
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \; find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
- name: Cache Binaryen - name: Cache Binaryen
uses: actions/cache@v2 uses: actions/cache@v3
id: cache-binaryen id: cache-binaryen
with: with:
key: binaryen-linux-asserts-v1 key: binaryen-linux-asserts-v1
@@ -231,7 +221,7 @@ jobs:
if: steps.cache-binaryen.outputs.cache-hit != 'true' if: steps.cache-binaryen.outputs.cache-hit != 'true'
run: make binaryen run: make binaryen
- name: Cache wasi-libc - name: Cache wasi-libc
uses: actions/cache@v2 uses: actions/cache@v3
id: cache-wasi-libc id: cache-wasi-libc
with: with:
key: wasi-libc-sysroot-linux-asserts-v5 key: wasi-libc-sysroot-linux-asserts-v5
@@ -279,18 +269,12 @@ jobs:
g++-arm-linux-gnueabihf \ g++-arm-linux-gnueabihf \
libc6-dev-armhf-cross libc6-dev-armhf-cross
- name: Install Go - name: Install Go
uses: actions/setup-go@v2 uses: actions/setup-go@v3
with: with:
go-version: '1.18.1' go-version: '1.19'
- name: Cache Go cache: true
uses: actions/cache@v2
with:
key: go-cache-linux-arm-v2-${{ hashFiles('go.mod') }}
path: |
~/.cache/go-build
~/go/pkg/mod
- name: Cache LLVM source - name: Cache LLVM source
uses: actions/cache@v2 uses: actions/cache@v3
id: cache-llvm-source id: cache-llvm-source
with: with:
key: llvm-source-14-linux-v2 key: llvm-source-14-linux-v2
@@ -304,7 +288,7 @@ jobs:
if: steps.cache-llvm-source.outputs.cache-hit != 'true' if: steps.cache-llvm-source.outputs.cache-hit != 'true'
run: make llvm-source run: make llvm-source
- name: Cache LLVM build - name: Cache LLVM build
uses: actions/cache@v2 uses: actions/cache@v3
id: cache-llvm-build id: cache-llvm-build
with: with:
key: llvm-build-14-linux-arm-v1 key: llvm-build-14-linux-arm-v1
@@ -322,7 +306,7 @@ jobs:
# Remove unnecessary object files (to reduce cache size). # Remove unnecessary object files (to reduce cache size).
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \; find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
- name: Cache Binaryen - name: Cache Binaryen
uses: actions/cache@v2 uses: actions/cache@v3
id: cache-binaryen id: cache-binaryen
with: with:
key: binaryen-linux-arm-v1 key: binaryen-linux-arm-v1
@@ -385,18 +369,12 @@ jobs:
libc6-dev-arm64-cross \ libc6-dev-arm64-cross \
ninja-build ninja-build
- name: Install Go - name: Install Go
uses: actions/setup-go@v2 uses: actions/setup-go@v3
with: with:
go-version: '1.18.1' go-version: '1.19'
- name: Cache Go cache: true
uses: actions/cache@v2
with:
key: go-cache-linux-arm64-v2-${{ hashFiles('go.mod') }}
path: |
~/.cache/go-build
~/go/pkg/mod
- name: Cache LLVM source - name: Cache LLVM source
uses: actions/cache@v2 uses: actions/cache@v3
id: cache-llvm-source id: cache-llvm-source
with: with:
key: llvm-source-14-linux-v1 key: llvm-source-14-linux-v1
@@ -410,7 +388,7 @@ jobs:
if: steps.cache-llvm-source.outputs.cache-hit != 'true' if: steps.cache-llvm-source.outputs.cache-hit != 'true'
run: make llvm-source run: make llvm-source
- name: Cache LLVM build - name: Cache LLVM build
uses: actions/cache@v2 uses: actions/cache@v3
id: cache-llvm-build id: cache-llvm-build
with: with:
key: llvm-build-14-linux-arm64-v1 key: llvm-build-14-linux-arm64-v1
@@ -426,7 +404,7 @@ jobs:
# Remove unnecessary object files (to reduce cache size). # Remove unnecessary object files (to reduce cache size).
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \; find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
- name: Cache Binaryen - name: Cache Binaryen
uses: actions/cache@v2 uses: actions/cache@v3
id: cache-binaryen id: cache-binaryen
with: with:
key: binaryen-linux-arm64-v1 key: binaryen-linux-arm64-v1
+7 -13
View File
@@ -15,10 +15,6 @@ jobs:
build-windows: build-windows:
runs-on: windows-2022 runs-on: windows-2022
steps: steps:
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: '1.18.1'
- uses: brechtm/setup-scoop@v2 - uses: brechtm/setup-scoop@v2
with: with:
scoop_update: 'false' scoop_update: 'false'
@@ -30,15 +26,13 @@ jobs:
uses: actions/checkout@v2 uses: actions/checkout@v2
with: with:
submodules: true submodules: true
- name: Cache Go - name: Install Go
uses: actions/cache@v2 uses: actions/setup-go@v3
with: with:
key: go-cache-windows-v1-${{ hashFiles('go.mod') }} go-version: '1.19'
path: | cache: true
~/AppData/Local/go-build
~/go/pkg/mod
- name: Cache LLVM source - name: Cache LLVM source
uses: actions/cache@v2 uses: actions/cache@v3
id: cache-llvm-source id: cache-llvm-source
with: with:
key: llvm-source-14-windows-v2 key: llvm-source-14-windows-v2
@@ -52,7 +46,7 @@ jobs:
if: steps.cache-llvm-source.outputs.cache-hit != 'true' if: steps.cache-llvm-source.outputs.cache-hit != 'true'
run: make llvm-source run: make llvm-source
- name: Cache LLVM build - name: Cache LLVM build
uses: actions/cache@v2 uses: actions/cache@v3
id: cache-llvm-build id: cache-llvm-build
with: with:
key: llvm-build-14-windows-v2 key: llvm-build-14-windows-v2
@@ -69,7 +63,7 @@ jobs:
# Remove unnecessary object files (to reduce cache size). # Remove unnecessary object files (to reduce cache size).
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \; find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
- name: Cache wasi-libc sysroot - name: Cache wasi-libc sysroot
uses: actions/cache@v2 uses: actions/cache@v3
id: cache-wasi-libc id: cache-wasi-libc
with: with:
key: wasi-libc-sysroot-v4 key: wasi-libc-sysroot-v4
+1 -1
View File
@@ -1,5 +1,5 @@
# tinygo-llvm stage obtains the llvm source for TinyGo # tinygo-llvm stage obtains the llvm source for TinyGo
FROM golang:1.18 AS tinygo-llvm FROM golang:1.19 AS tinygo-llvm
RUN apt-get update && \ RUN apt-get update && \
apt-get install -y apt-utils make cmake clang-11 binutils-avr gcc-avr avr-libc ninja-build apt-get install -y apt-utils make cmake clang-11 binutils-avr gcc-avr avr-libc ninja-build
+30 -11
View File
@@ -326,11 +326,14 @@ TEST_PACKAGES_FAST += crypto/elliptic/internal/fiat
endif endif
# archive/zip requires os.ReadAt, which is not yet supported on windows # archive/zip requires os.ReadAt, which is not yet supported on windows
# compress/flate appears to hang on wasi
# compress/lzw appears to hang on wasi
# crypto/hmac fails on wasi, it exits with a "slice out of range" panic
# debug/plan9obj requires os.ReadAt, which is not yet supported on windows # debug/plan9obj requires os.ReadAt, which is not yet supported on windows
# io/fs requires os.ReadDir, which is not yet supported on windows or wasi # io/ioutil requires os.ReadDir, which is not yet supported on windows or wasi
# strconv requires recover() which is not yet supported on wasi
# text/template/parse requires recover(), which is not yet supported on wasi
# testing/fstest requires os.ReadDir, which is not yet supported on windows or wasi # testing/fstest requires os.ReadDir, which is not yet supported on windows or wasi
# compress/flate fails windows go 1.18, https://github.com/tinygo-org/tinygo/issues/2762
# compress/lzw fails windows go 1.18 wasi, https://github.com/tinygo-org/tinygo/issues/2762
# Additional standard library packages that pass tests on individual platforms # Additional standard library packages that pass tests on individual platforms
TEST_PACKAGES_LINUX := \ TEST_PACKAGES_LINUX := \
@@ -340,7 +343,6 @@ TEST_PACKAGES_LINUX := \
crypto/hmac \ crypto/hmac \
debug/dwarf \ debug/dwarf \
debug/plan9obj \ debug/plan9obj \
io/fs \
io/ioutil \ io/ioutil \
strconv \ strconv \
testing/fstest \ testing/fstest \
@@ -349,7 +351,12 @@ TEST_PACKAGES_LINUX := \
TEST_PACKAGES_DARWIN := $(TEST_PACKAGES_LINUX) TEST_PACKAGES_DARWIN := $(TEST_PACKAGES_LINUX)
TEST_PACKAGES_WINDOWS := \ TEST_PACKAGES_WINDOWS := \
compress/lzw compress/flate \
compress/lzw \
crypto/hmac \
strconv \
text/template/parse \
$(nil)
# Report platforms on which each standard library package is known to pass tests # Report platforms on which each standard library package is known to pass tests
jointmp := $(shell echo /tmp/join.$$$$) jointmp := $(shell echo /tmp/join.$$$$)
@@ -364,12 +371,15 @@ report-stdlib-tests-pass:
# Standard library packages that pass tests quickly on the current platform # Standard library packages that pass tests quickly on the current platform
ifeq ($(shell uname),Darwin) ifeq ($(shell uname),Darwin)
TEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_DARWIN) TEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_DARWIN)
TEST_IOFS := true
endif endif
ifeq ($(shell uname),Linux) ifeq ($(shell uname),Linux)
TEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_LINUX) TEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_LINUX)
TEST_IOFS := true
endif endif
ifeq ($(OS),Windows_NT) ifeq ($(OS),Windows_NT)
TEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_WINDOWS) TEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_WINDOWS)
TEST_IOFS := false
endif endif
# Test known-working standard library packages. # Test known-working standard library packages.
@@ -377,6 +387,12 @@ endif
.PHONY: tinygo-test .PHONY: tinygo-test
tinygo-test: tinygo-test:
$(TINYGO) test $(TEST_PACKAGES_HOST) $(TEST_PACKAGES_SLOW) $(TINYGO) test $(TEST_PACKAGES_HOST) $(TEST_PACKAGES_SLOW)
@# io/fs requires os.ReadDir, not yet supported on windows or wasi. It also
@# requires a large stack-size. Hence, io/fs is only run conditionally.
@# For more details, see the comments on issue #3143.
ifeq ($(TEST_IOFS),true)
$(TINYGO) test -stack-size=6MB io/fs
endif
tinygo-test-fast: tinygo-test-fast:
$(TINYGO) test $(TEST_PACKAGES_HOST) $(TINYGO) test $(TEST_PACKAGES_HOST)
tinygo-bench: tinygo-bench:
@@ -386,9 +402,9 @@ tinygo-bench-fast:
# Same thing, except for wasi rather than the current platform. # Same thing, except for wasi rather than the current platform.
tinygo-test-wasi: tinygo-test-wasi:
$(TINYGO) test -target wasi $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW) $(TINYGO) test -target wasi $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW) ./tests/runtime_wasi
tinygo-test-wasi-fast: tinygo-test-wasi-fast:
$(TINYGO) test -target wasi $(TEST_PACKAGES_FAST) $(TINYGO) test -target wasi $(TEST_PACKAGES_FAST) ./tests/runtime_wasi
tinygo-bench-wasi: tinygo-bench-wasi:
$(TINYGO) test -target wasi -bench . $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW) $(TINYGO) test -target wasi -bench . $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW)
tinygo-bench-wasi-fast: tinygo-bench-wasi-fast:
@@ -410,6 +426,7 @@ tinygo-baremetal:
.PHONY: smoketest .PHONY: smoketest
smoketest: smoketest:
$(TINYGO) version $(TINYGO) version
$(TINYGO) targets > /dev/null
# regression test for #2892 # regression test for #2892
cd tests/testing/recurse && ($(TINYGO) test ./... > recurse.log && cat recurse.log && test $$(wc -l < recurse.log) = 2 && rm recurse.log) cd tests/testing/recurse && ($(TINYGO) test ./... > recurse.log && cat recurse.log && test $$(wc -l < recurse.log) = 2 && rm recurse.log)
# compile-only platform-independent examples # compile-only platform-independent examples
@@ -519,6 +536,8 @@ endif
@$(MD5SUM) test.hex @$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=feather-m4 examples/blinky1 $(TINYGO) build -size short -o test.hex -target=feather-m4 examples/blinky1
@$(MD5SUM) test.hex @$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=matrixportal-m4 examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=pybadge examples/blinky1 $(TINYGO) build -size short -o test.hex -target=pybadge examples/blinky1
@$(MD5SUM) test.hex @$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=metro-m4-airlift examples/blinky1 $(TINYGO) build -size short -o test.hex -target=metro-m4-airlift examples/blinky1
@@ -599,7 +618,7 @@ endif
@$(MD5SUM) test.hex @$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=challenger-rp2040 examples/blinky1 $(TINYGO) build -size short -o test.hex -target=challenger-rp2040 examples/blinky1
@$(MD5SUM) test.hex @$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=trinkey-qt2040 examples/adc_rp2040 $(TINYGO) build -size short -o test.hex -target=trinkey-qt2040 examples/temp
@$(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
@@ -681,7 +700,9 @@ ifneq ($(XTENSA), 0)
$(TINYGO) build -size short -o test.bin -target mch2022 examples/serial $(TINYGO) build -size short -o test.bin -target mch2022 examples/serial
@$(MD5SUM) test.bin @$(MD5SUM) test.bin
endif endif
$(TINYGO) build -size short -o test.bin -target=esp32c3 examples/serial $(TINYGO) build -size short -o test.bin -target=esp32c3 examples/serial
@$(MD5SUM) test.bin
$(TINYGO) build -size short -o test.bin -target=esp32c3-12f examples/serial
@$(MD5SUM) test.bin @$(MD5SUM) test.bin
$(TINYGO) build -size short -o test.bin -target=m5stamp-c3 examples/serial $(TINYGO) build -size short -o test.bin -target=m5stamp-c3 examples/serial
@$(MD5SUM) test.bin @$(MD5SUM) test.bin
@@ -689,8 +710,6 @@ endif
@$(MD5SUM) test.bin @$(MD5SUM) test.bin
$(TINYGO) build -size short -o test.hex -target=hifive1b examples/blinky1 $(TINYGO) build -size short -o test.hex -target=hifive1b examples/blinky1
@$(MD5SUM) test.hex @$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=hifive1-qemu examples/serial
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=maixbit examples/blinky1 $(TINYGO) build -size short -o test.hex -target=maixbit examples/blinky1
@$(MD5SUM) test.hex @$(MD5SUM) test.hex
ifneq ($(WASM), 0) ifneq ($(WASM), 0)
+1 -1
View File
@@ -125,7 +125,7 @@ The following 91 microcontroller boards are currently supported:
* [Seeed LoRa-E5 Development Kit](https://www.seeedstudio.com/LoRa-E5-Dev-Kit-p-4868.html) * [Seeed LoRa-E5 Development Kit](https://www.seeedstudio.com/LoRa-E5-Dev-Kit-p-4868.html)
* [Seeed Sipeed MAix BiT](https://www.seeedstudio.com/Sipeed-MAix-BiT-for-RISC-V-AI-IoT-p-2872.html) * [Seeed Sipeed MAix BiT](https://www.seeedstudio.com/Sipeed-MAix-BiT-for-RISC-V-AI-IoT-p-2872.html)
* [Seeed Wio Terminal](https://www.seeedstudio.com/Wio-Terminal-p-4509.html) * [Seeed Wio Terminal](https://www.seeedstudio.com/Wio-Terminal-p-4509.html)
* [SiFIve HiFive1 Rev B](https://www.sifive.com/boards/hifive1) * [SiFIve HiFive1 Rev B](https://www.sifive.com/boards/hifive1-rev-b)
* [Sparkfun Thing Plus RP2040](https://www.sparkfun.com/products/17745) * [Sparkfun Thing Plus RP2040](https://www.sparkfun.com/products/17745)
* [ST Micro "Nucleo" F103RB](https://www.st.com/en/evaluation-tools/nucleo-f103rb.html) * [ST Micro "Nucleo" F103RB](https://www.st.com/en/evaluation-tools/nucleo-f103rb.html)
* [ST Micro "Nucleo" F722ZE](https://www.st.com/en/evaluation-tools/nucleo-f722ze.html) * [ST Micro "Nucleo" F722ZE](https://www.st.com/en/evaluation-tools/nucleo-f722ze.html)
+1 -1
View File
@@ -178,7 +178,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
Scheduler: config.Scheduler(), Scheduler: config.Scheduler(),
AutomaticStackSize: config.AutomaticStackSize(), AutomaticStackSize: config.AutomaticStackSize(),
DefaultStackSize: config.Target.DefaultStackSize, DefaultStackSize: config.StackSize(),
NeedsStackObjects: config.NeedsStackObjects(), NeedsStackObjects: config.NeedsStackObjects(),
Debug: true, Debug: true,
} }
+57 -16
View File
@@ -32,6 +32,7 @@ type cgoPackage struct {
errors []error errors []error
currentDir string // current working directory currentDir string // current working directory
packageDir string // full path to the package to process packageDir string // full path to the package to process
importPath string
fset *token.FileSet fset *token.FileSet
tokenFiles map[string]*token.File tokenFiles map[string]*token.File
definedGlobally map[string]ast.Node definedGlobally map[string]ast.Node
@@ -39,12 +40,15 @@ type cgoPackage struct {
cflags []string // CFlags from #cgo lines cflags []string // CFlags from #cgo lines
ldflags []string // LDFlags from #cgo lines ldflags []string // LDFlags from #cgo lines
visitedFiles map[string][]byte visitedFiles map[string][]byte
cgoHeaders []string
} }
// cgoFile holds information only for a single Go file (with one or more // cgoFile holds information only for a single Go file (with one or more
// `import "C"` statements). // `import "C"` statements).
type cgoFile struct { type cgoFile struct {
*cgoPackage *cgoPackage
file *ast.File
index int
defined map[string]ast.Node defined map[string]ast.Node
names map[string]clangCursor names map[string]clangCursor
} }
@@ -158,9 +162,10 @@ func GoBytes(ptr unsafe.Pointer, length C.int) []byte {
// functions), the CFLAGS and LDFLAGS found in #cgo lines, and a map of file // functions), the CFLAGS and LDFLAGS found in #cgo lines, and a map of file
// hashes of the accessed C header files. If there is one or more error, it // hashes of the accessed C header files. If there is one or more error, it
// returns these in the []error slice but still modifies the AST. // returns these in the []error slice but still modifies the AST.
func Process(files []*ast.File, dir string, fset *token.FileSet, cflags []string, clangHeaders string) (*ast.File, []string, []string, []string, map[string][]byte, []error) { func Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cflags []string, clangHeaders string) (*ast.File, []string, []string, []string, map[string][]byte, []error) {
p := &cgoPackage{ p := &cgoPackage{
currentDir: dir, currentDir: dir,
importPath: importPath,
fset: fset, fset: fset,
tokenFiles: map[string]*token.File{}, tokenFiles: map[string]*token.File{},
definedGlobally: map[string]ast.Node{}, definedGlobally: map[string]ast.Node{},
@@ -210,13 +215,13 @@ func Process(files []*ast.File, dir string, fset *token.FileSet, cflags []string
} }
} }
// Patch some types, for example *C.char in C.CString. // Patch some types, for example *C.char in C.CString.
cf := p.newCGoFile() cf := p.newCGoFile(nil, -1) // dummy *cgoFile for the walker
astutil.Apply(p.generated, func(cursor *astutil.Cursor) bool { astutil.Apply(p.generated, func(cursor *astutil.Cursor) bool {
return cf.walker(cursor, nil) return cf.walker(cursor, nil)
}, nil) }, nil)
// Find `import "C"` C fragments in the file. // Find `import "C"` C fragments in the file.
cgoHeaders := make([]string, len(files)) // combined CGo header fragment for each file p.cgoHeaders = make([]string, len(files)) // combined CGo header fragment for each file
for i, f := range files { for i, f := range files {
var cgoHeader string var cgoHeader string
for i := 0; i < len(f.Decls); i++ { for i := 0; i < len(f.Decls); i++ {
@@ -275,7 +280,7 @@ func Process(files []*ast.File, dir string, fset *token.FileSet, cflags []string
cgoHeader += fragment cgoHeader += fragment
} }
cgoHeaders[i] = cgoHeader p.cgoHeaders[i] = cgoHeader
} }
// Define CFlags that will be used while parsing the package. // Define CFlags that will be used while parsing the package.
@@ -289,7 +294,7 @@ func Process(files []*ast.File, dir string, fset *token.FileSet, cflags []string
} }
// Retrieve types such as C.int, C.longlong, etc from C. // Retrieve types such as C.int, C.longlong, etc from C.
p.newCGoFile().readNames(builtinAliasTypedefs, cflagsForCGo, "", func(names map[string]clangCursor) { p.newCGoFile(nil, -1).readNames(builtinAliasTypedefs, cflagsForCGo, "", func(names map[string]clangCursor) {
gen := &ast.GenDecl{ gen := &ast.GenDecl{
TokPos: token.NoPos, TokPos: token.NoPos,
Tok: token.TYPE, Tok: token.TYPE,
@@ -303,8 +308,8 @@ func Process(files []*ast.File, dir string, fset *token.FileSet, cflags []string
// Process CGo imports for each file. // Process CGo imports for each file.
for i, f := range files { for i, f := range files {
cf := p.newCGoFile() cf := p.newCGoFile(f, i)
cf.readNames(cgoHeaders[i], cflagsForCGo, filepath.Base(fset.File(f.Pos()).Name()), func(names map[string]clangCursor) { cf.readNames(p.cgoHeaders[i], cflagsForCGo, filepath.Base(fset.File(f.Pos()).Name()), func(names map[string]clangCursor) {
for _, name := range builtinAliases { for _, name := range builtinAliases {
// Names such as C.int should not be obtained from C. // Names such as C.int should not be obtained from C.
// This works around an issue in picolibc that has `#define int` // This works around an issue in picolibc that has `#define int`
@@ -320,12 +325,14 @@ func Process(files []*ast.File, dir string, fset *token.FileSet, cflags []string
// Print the newly generated in-memory AST, for debugging. // Print the newly generated in-memory AST, for debugging.
//ast.Print(fset, p.generated) //ast.Print(fset, p.generated)
return p.generated, cgoHeaders, p.cflags, p.ldflags, p.visitedFiles, p.errors return p.generated, p.cgoHeaders, p.cflags, p.ldflags, p.visitedFiles, p.errors
} }
func (p *cgoPackage) newCGoFile() *cgoFile { func (p *cgoPackage) newCGoFile(file *ast.File, index int) *cgoFile {
return &cgoFile{ return &cgoFile{
cgoPackage: p, cgoPackage: p,
file: file,
index: index,
defined: make(map[string]ast.Node), defined: make(map[string]ast.Node),
names: make(map[string]clangCursor), names: make(map[string]clangCursor),
} }
@@ -1117,8 +1124,11 @@ func (f *cgoFile) getASTDeclName(name string, found clangCursor, iscall bool) st
return alias return alias
} }
node := f.getASTDeclNode(name, found, iscall) node := f.getASTDeclNode(name, found, iscall)
if _, ok := node.(*ast.FuncDecl); ok && !iscall { if node, ok := node.(*ast.FuncDecl); ok {
return "C." + name + "$funcaddr" if !iscall {
return node.Name.Name + "$funcaddr"
}
return node.Name.Name
} }
return "C." + name return "C." + name
} }
@@ -1142,7 +1152,7 @@ func (f *cgoFile) getASTDeclNode(name string, found clangCursor, iscall bool) as
// Original cgo reports an error like // Original cgo reports an error like
// cgo: inconsistent definitions for C.myint // cgo: inconsistent definitions for C.myint
// which is far less helpful. // which is far less helpful.
f.addError(getPos(node), "defined previously at "+f.fset.Position(getPos(newNode)).String()+" with a different type") f.addError(getPos(node), name+" defined previously at "+f.fset.Position(getPos(newNode)).String()+" with a different type")
} }
f.defined[name] = node f.defined[name] = node
return node return node
@@ -1150,11 +1160,39 @@ func (f *cgoFile) getASTDeclNode(name string, found clangCursor, iscall bool) as
// The declaration has no AST node. Create it now. // The declaration has no AST node. Create it now.
f.defined[name] = nil f.defined[name] = nil
node, elaboratedType := f.createASTNode(name, found) node, extra := f.createASTNode(name, found)
f.defined[name] = node f.defined[name] = node
f.definedGlobally[name] = node
switch node := node.(type) { switch node := node.(type) {
case *ast.FuncDecl: case *ast.FuncDecl:
if strings.HasPrefix(node.Doc.List[0].Text, "//export _Cgo_static_") {
// Static function. Only accessible in the current Go file.
globalName := strings.TrimPrefix(node.Doc.List[0].Text, "//export ")
// Make an alias. Normally this is done using the alias function
// attribute, but MacOS for some reason doesn't support this (even
// though the linker has support for aliases in the form of N_INDR).
// Therefore, create an actual function for MacOS.
var params []string
for _, param := range node.Type.Params.List {
params = append(params, param.Names[0].Name)
}
callInst := fmt.Sprintf("%s(%s);", name, strings.Join(params, ", "))
if node.Type.Results != nil {
callInst = "return " + callInst
}
aliasDeclaration := fmt.Sprintf(`
#ifdef __APPLE__
%s {
%s
}
#else
extern __typeof(%s) %s __attribute__((alias(%#v)));
#endif
`, extra.(string), callInst, name, globalName, name)
f.cgoHeaders[f.index] += "\n\n" + aliasDeclaration
} else {
// Regular (non-static) function.
f.definedGlobally[name] = node
}
f.generated.Decls = append(f.generated.Decls, node) f.generated.Decls = append(f.generated.Decls, node)
// Also add a declaration like the following: // Also add a declaration like the following:
// var C.foo$funcaddr unsafe.Pointer // var C.foo$funcaddr unsafe.Pointer
@@ -1162,7 +1200,7 @@ func (f *cgoFile) getASTDeclNode(name string, found clangCursor, iscall bool) as
Tok: token.VAR, Tok: token.VAR,
Specs: []ast.Spec{ Specs: []ast.Spec{
&ast.ValueSpec{ &ast.ValueSpec{
Names: []*ast.Ident{{Name: "C." + name + "$funcaddr"}}, Names: []*ast.Ident{{Name: node.Name.Name + "$funcaddr"}},
Type: &ast.SelectorExpr{ Type: &ast.SelectorExpr{
X: &ast.Ident{Name: "unsafe"}, X: &ast.Ident{Name: "unsafe"},
Sel: &ast.Ident{Name: "Pointer"}, Sel: &ast.Ident{Name: "Pointer"},
@@ -1171,8 +1209,10 @@ func (f *cgoFile) getASTDeclNode(name string, found clangCursor, iscall bool) as
}, },
}) })
case *ast.GenDecl: case *ast.GenDecl:
f.definedGlobally[name] = node
f.generated.Decls = append(f.generated.Decls, node) f.generated.Decls = append(f.generated.Decls, node)
case *ast.TypeSpec: case *ast.TypeSpec:
f.definedGlobally[name] = node
f.generated.Decls = append(f.generated.Decls, &ast.GenDecl{ f.generated.Decls = append(f.generated.Decls, &ast.GenDecl{
Tok: token.TYPE, Tok: token.TYPE,
Specs: []ast.Spec{node}, Specs: []ast.Spec{node},
@@ -1186,7 +1226,8 @@ func (f *cgoFile) getASTDeclNode(name string, found clangCursor, iscall bool) as
// If this is a struct or union it may need bitfields or union accessor // If this is a struct or union it may need bitfields or union accessor
// methods. // methods.
if elaboratedType != nil { switch elaboratedType := extra.(type) {
case *elaboratedTypeInfo:
// Add struct bitfields. // Add struct bitfields.
for _, bitfield := range elaboratedType.bitfields { for _, bitfield := range elaboratedType.bitfields {
f.createBitfieldGetter(bitfield, "C."+name) f.createBitfieldGetter(bitfield, "C."+name)
+1 -1
View File
@@ -48,7 +48,7 @@ func TestCGo(t *testing.T) {
} }
// Process the AST with CGo. // Process the AST with CGo.
cgoAST, _, _, _, _, cgoErrors := Process([]*ast.File{f}, "testdata", fset, cflags, "") cgoAST, _, _, _, _, cgoErrors := Process([]*ast.File{f}, "testdata", "main", fset, cflags, "")
// Check the AST for type errors. // Check the AST for type errors.
var typecheckErrors []error var typecheckErrors []error
+33 -4
View File
@@ -4,7 +4,9 @@ package cgo
// modification. It does not touch the AST itself. // modification. It does not touch the AST itself.
import ( import (
"crypto/sha256"
"crypto/sha512" "crypto/sha512"
"encoding/hex"
"fmt" "fmt"
"go/ast" "go/ast"
"go/scanner" "go/scanner"
@@ -43,6 +45,8 @@ typedef struct {
GoCXCursor tinygo_clang_getTranslationUnitCursor(CXTranslationUnit tu); GoCXCursor tinygo_clang_getTranslationUnitCursor(CXTranslationUnit tu);
unsigned tinygo_clang_visitChildren(GoCXCursor parent, CXCursorVisitor visitor, CXClientData client_data); unsigned tinygo_clang_visitChildren(GoCXCursor parent, CXCursorVisitor visitor, CXClientData client_data);
CXString tinygo_clang_getCursorSpelling(GoCXCursor c); CXString tinygo_clang_getCursorSpelling(GoCXCursor c);
CXString tinygo_clang_getCursorPrettyPrinted(GoCXCursor c, CXPrintingPolicy Policy);
CXPrintingPolicy tinygo_clang_getCursorPrintingPolicy(GoCXCursor c);
enum CXCursorKind tinygo_clang_getCursorKind(GoCXCursor c); enum CXCursorKind tinygo_clang_getCursorKind(GoCXCursor c);
CXType tinygo_clang_getCursorType(GoCXCursor c); CXType tinygo_clang_getCursorType(GoCXCursor c);
GoCXCursor tinygo_clang_getTypeDeclaration(CXType t); GoCXCursor tinygo_clang_getTypeDeclaration(CXType t);
@@ -50,6 +54,7 @@ CXType tinygo_clang_getTypedefDeclUnderlyingType(GoCXCursor c);
CXType tinygo_clang_getCursorResultType(GoCXCursor c); CXType tinygo_clang_getCursorResultType(GoCXCursor c);
int tinygo_clang_Cursor_getNumArguments(GoCXCursor c); int tinygo_clang_Cursor_getNumArguments(GoCXCursor c);
GoCXCursor tinygo_clang_Cursor_getArgument(GoCXCursor c, unsigned i); GoCXCursor tinygo_clang_Cursor_getArgument(GoCXCursor c, unsigned i);
enum CX_StorageClass tinygo_clang_Cursor_getStorageClass(GoCXCursor c);
CXSourceLocation tinygo_clang_getCursorLocation(GoCXCursor c); CXSourceLocation tinygo_clang_getCursorLocation(GoCXCursor c);
CXSourceRange tinygo_clang_getCursorExtent(GoCXCursor c); CXSourceRange tinygo_clang_getCursorExtent(GoCXCursor c);
CXTranslationUnit tinygo_clang_Cursor_getTranslationUnit(GoCXCursor c); CXTranslationUnit tinygo_clang_Cursor_getTranslationUnit(GoCXCursor c);
@@ -189,7 +194,7 @@ func (f *cgoFile) readNames(fragment string, cflags []string, filename string, c
// Convert the AST node under the given Clang cursor to a Go AST node and return // Convert the AST node under the given Clang cursor to a Go AST node and return
// it. // it.
func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, *elaboratedTypeInfo) { func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) {
kind := C.tinygo_clang_getCursorKind(c) kind := C.tinygo_clang_getCursorKind(c)
pos := f.getCursorPosition(c) pos := f.getCursorPosition(c)
switch kind { switch kind {
@@ -200,19 +205,43 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, *elaborat
Kind: ast.Fun, Kind: ast.Fun,
Name: "C." + name, Name: "C." + name,
} }
exportName := name
localName := name
var stringSignature string
if C.tinygo_clang_Cursor_getStorageClass(c) == C.CX_SC_Static {
// A static function is assigned a globally unique symbol name based
// on the file path (like _Cgo_static_2d09198adbf58f4f4655_foo) and
// has a different Go name in the form of C.foo!symbols.go instead
// of just C.foo.
path := f.importPath + "/" + filepath.Base(f.fset.File(f.file.Pos()).Name())
staticIDBuf := sha256.Sum256([]byte(path))
staticID := hex.EncodeToString(staticIDBuf[:10])
exportName = "_Cgo_static_" + staticID + "_" + name
localName = name + "!" + filepath.Base(path)
// Create a signature. This is necessary for MacOS to forward the
// call, because MacOS doesn't support aliases like ELF and PE do.
// (There is N_INDR but __attribute__((alias("..."))) doesn't work).
policy := C.tinygo_clang_getCursorPrintingPolicy(c)
defer C.clang_PrintingPolicy_dispose(policy)
C.clang_PrintingPolicy_setProperty(policy, C.CXPrintingPolicy_TerseOutput, 1)
stringSignature = getString(C.tinygo_clang_getCursorPrettyPrinted(c, policy))
stringSignature = strings.Replace(stringSignature, " "+name+"(", " "+exportName+"(", 1)
stringSignature = strings.TrimPrefix(stringSignature, "static ")
}
args := make([]*ast.Field, numArgs) args := make([]*ast.Field, numArgs)
decl := &ast.FuncDecl{ decl := &ast.FuncDecl{
Doc: &ast.CommentGroup{ Doc: &ast.CommentGroup{
List: []*ast.Comment{ List: []*ast.Comment{
{ {
Slash: pos - 1, Slash: pos - 1,
Text: "//export " + name, Text: "//export " + exportName,
}, },
}, },
}, },
Name: &ast.Ident{ Name: &ast.Ident{
NamePos: pos, NamePos: pos,
Name: "C." + name, Name: "C." + localName,
Obj: obj, Obj: obj,
}, },
Type: &ast.FuncType{ Type: &ast.FuncType{
@@ -263,7 +292,7 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, *elaborat
} }
} }
obj.Decl = decl obj.Decl = decl
return decl, nil return decl, stringSignature
case C.CXCursor_StructDecl, C.CXCursor_UnionDecl: case C.CXCursor_StructDecl, C.CXCursor_UnionDecl:
typ := f.makeASTRecordType(c, pos) typ := f.makeASTRecordType(c, pos)
typeName := "C." + name typeName := "C." + name
+12
View File
@@ -17,6 +17,14 @@ CXString tinygo_clang_getCursorSpelling(CXCursor c) {
return clang_getCursorSpelling(c); return clang_getCursorSpelling(c);
} }
CXString tinygo_clang_getCursorPrettyPrinted(CXCursor c, CXPrintingPolicy policy) {
return clang_getCursorPrettyPrinted(c, policy);
}
CXPrintingPolicy tinygo_clang_getCursorPrintingPolicy(CXCursor c) {
return clang_getCursorPrintingPolicy(c);
}
enum CXCursorKind tinygo_clang_getCursorKind(CXCursor c) { enum CXCursorKind tinygo_clang_getCursorKind(CXCursor c) {
return clang_getCursorKind(c); return clang_getCursorKind(c);
} }
@@ -45,6 +53,10 @@ CXCursor tinygo_clang_Cursor_getArgument(CXCursor c, unsigned i) {
return clang_Cursor_getArgument(c, i); return clang_Cursor_getArgument(c, i);
} }
enum CX_StorageClass tinygo_clang_Cursor_getStorageClass(CXCursor c) {
return clang_Cursor_getStorageClass(c);
}
CXSourceLocation tinygo_clang_getCursorLocation(CXCursor c) { CXSourceLocation tinygo_clang_getCursorLocation(CXCursor c) {
return clang_getCursorLocation(c); return clang_getCursorLocation(c);
} }
+2
View File
@@ -5,6 +5,7 @@ package main
int foo(int a, int b); int foo(int a, int b);
void variadic0(); void variadic0();
void variadic2(int x, int y, ...); void variadic2(int x, int y, ...);
static void staticfunc(int x);
// Global variable signatures. // Global variable signatures.
extern int someValue; extern int someValue;
@@ -16,6 +17,7 @@ func accessFunctions() {
C.foo(3, 4) C.foo(3, 4)
C.variadic0() C.variadic0()
C.variadic2(3, 5) C.variadic2(3, 5)
C.staticfunc(3)
} }
func accessGlobals() { func accessGlobals() {
+5
View File
@@ -55,5 +55,10 @@ func C.variadic2(x C.int, y C.int)
var C.variadic2$funcaddr unsafe.Pointer var C.variadic2$funcaddr unsafe.Pointer
//export _Cgo_static_173c95a79b6df1980521_staticfunc
func C.staticfunc!symbols.go(x C.int)
var C.staticfunc!symbols.go$funcaddr unsafe.Pointer
//go:extern someValue //go:extern someValue
var C.someValue C.int var C.someValue C.int
+17 -1
View File
@@ -175,6 +175,15 @@ func (c *Config) AutomaticStackSize() bool {
return false return false
} }
// StackSize returns the default stack size to be used for goroutines, if the
// stack size could not be determined automatically at compile time.
func (c *Config) StackSize() uint64 {
if c.Options.StackSize != 0 {
return c.Options.StackSize
}
return c.Target.DefaultStackSize
}
// UseThinLTO returns whether ThinLTO should be used for the given target. Some // UseThinLTO returns whether ThinLTO should be used for the given target. Some
// targets (such as wasm) are not yet supported. // targets (such as wasm) are not yet supported.
// We should try and remove as many exceptions as possible in the future, so // We should try and remove as many exceptions as possible in the future, so
@@ -457,7 +466,14 @@ func (c *Config) OpenOCDConfiguration() (args []string, err error) {
args = append(args, "-c", cmd) args = append(args, "-c", cmd)
} }
if c.Target.OpenOCDTransport != "" { if c.Target.OpenOCDTransport != "" {
args = append(args, "-c", "transport select "+c.Target.OpenOCDTransport) transport := c.Target.OpenOCDTransport
if transport == "swd" {
switch openocdInterface {
case "stlink-dap":
transport = "dapdirect_swd"
}
}
args = append(args, "-c", "transport select "+transport)
} }
args = append(args, "-f", "target/"+c.Target.OpenOCDTarget+".cfg") args = append(args, "-f", "target/"+c.Target.OpenOCDTarget+".cfg")
return args, nil return args, nil
+3
View File
@@ -28,6 +28,7 @@ type Options struct {
GC string GC string
PanicStrategy string PanicStrategy string
Scheduler string Scheduler string
StackSize uint64 // goroutine stack size (if none could be automatically determined)
Serial string Serial string
Work bool // -work flag to print temporary build directory Work bool // -work flag to print temporary build directory
InterpTimeout time.Duration InterpTimeout time.Duration
@@ -49,6 +50,8 @@ type Options struct {
LLVMFeatures string LLVMFeatures string
Directory string Directory string
PrintJSON bool PrintJSON bool
Monitor bool
BaudRate int
} }
// Verify performs a validation on the given options, raising an error if options are not valid. // Verify performs a validation on the given options, raising an error if options are not valid.
+17 -10
View File
@@ -65,7 +65,7 @@ type TargetSpec struct {
} }
// overrideProperties overrides all properties that are set in child into itself using reflection. // overrideProperties overrides all properties that are set in child into itself using reflection.
func (spec *TargetSpec) overrideProperties(child *TargetSpec) { func (spec *TargetSpec) overrideProperties(child *TargetSpec) error {
specType := reflect.TypeOf(spec).Elem() specType := reflect.TypeOf(spec).Elem()
specValue := reflect.ValueOf(spec).Elem() specValue := reflect.ValueOf(spec).Elem()
childValue := reflect.ValueOf(child).Elem() childValue := reflect.ValueOf(child).Elem()
@@ -95,14 +95,15 @@ func (spec *TargetSpec) overrideProperties(child *TargetSpec) {
for j := i + 1; j < dst.Len(); j++ { for j := i + 1; j < dst.Len(); j++ {
w := dst.Index(j).String() w := dst.Index(j).String()
if v == w { if v == w {
panic("duplicate value '" + v + "' in field : " + field.Name) return fmt.Errorf("duplicate value '%s' in field %s", v, field.Name)
} }
} }
} }
default: default:
panic("unknown field type : " + kind.String()) return fmt.Errorf("unknown field type: %s", kind)
} }
} }
return nil
} }
// load reads a target specification from the JSON in the given io.Reader. It // load reads a target specification from the JSON in the given io.Reader. It
@@ -117,10 +118,10 @@ func (spec *TargetSpec) load(r io.Reader) error {
} }
// loadFromGivenStr loads the TargetSpec from the given string that could be: // loadFromGivenStr loads the TargetSpec from the given string that could be:
// - targets/ directory inside the compiler sources // - targets/ directory inside the compiler sources
// - a relative or absolute path to custom (project specific) target specification .json file; // - a relative or absolute path to custom (project specific) target specification .json file;
// the Inherits[] could contain the files from target folder (ex. stm32f4disco) // the Inherits[] could contain the files from target folder (ex. stm32f4disco)
// as well as path to custom files (ex. myAwesomeProject.json) // as well as path to custom files (ex. myAwesomeProject.json)
func (spec *TargetSpec) loadFromGivenStr(str string) error { func (spec *TargetSpec) loadFromGivenStr(str string) error {
path := "" path := ""
if strings.HasSuffix(str, ".json") { if strings.HasSuffix(str, ".json") {
@@ -150,11 +151,17 @@ func (spec *TargetSpec) resolveInherits() error {
if err != nil { if err != nil {
return err return err
} }
newSpec.overrideProperties(subtarget) err = newSpec.overrideProperties(subtarget)
if err != nil {
return err
}
} }
// When all properties are loaded, make sure they are properly inherited. // When all properties are loaded, make sure they are properly inherited.
newSpec.overrideProperties(spec) err := newSpec.overrideProperties(spec)
if err != nil {
return err
}
*spec = *newSpec *spec = *newSpec
return nil return nil
@@ -221,7 +228,7 @@ func LoadTarget(options *Options) (*TargetSpec, error) {
// it includes all parents as specified in the "inherits" key. // it includes all parents as specified in the "inherits" key.
err = spec.resolveInherits() err = spec.resolveInherits()
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("%s : %w", options.Target, err)
} }
if spec.Scheduler == "asyncify" { if spec.Scheduler == "asyncify" {
+1 -1
View File
@@ -79,7 +79,7 @@ func TestCompiler(t *testing.T) {
RelocationModel: config.RelocationModel(), RelocationModel: config.RelocationModel(),
Scheduler: config.Scheduler(), Scheduler: config.Scheduler(),
AutomaticStackSize: config.AutomaticStackSize(), AutomaticStackSize: config.AutomaticStackSize(),
DefaultStackSize: config.Target.DefaultStackSize, DefaultStackSize: config.StackSize(),
NeedsStackObjects: config.NeedsStackObjects(), NeedsStackObjects: config.NeedsStackObjects(),
} }
machine, err := NewTargetMachine(compilerConfig) machine, err := NewTargetMachine(compilerConfig)
+12 -10
View File
@@ -163,18 +163,20 @@ func (c *compilerContext) getFunction(fn *ssa.Function) llvm.Value {
// External/exported functions may not retain pointer values. // External/exported functions may not retain pointer values.
// https://golang.org/cmd/cgo/#hdr-Passing_pointers // https://golang.org/cmd/cgo/#hdr-Passing_pointers
if info.exported { if info.exported {
// Set the wasm-import-module attribute if the function's module is set. if c.archFamily() == "wasm32" {
if info.module != "" {
// We need to add the wasm-import-module and the wasm-import-name // We need to add the wasm-import-module and the wasm-import-name
wasmImportModuleAttr := c.ctx.CreateStringAttribute("wasm-import-module", info.module) // attributes.
llvmFn.AddFunctionAttr(wasmImportModuleAttr) module := info.module
if module == "" {
// Add the Wasm Import Name, if we are a named wasm import module = "env"
if info.importName != "" {
wasmImportNameAttr := c.ctx.CreateStringAttribute("wasm-import-name", info.importName)
llvmFn.AddFunctionAttr(wasmImportNameAttr)
} }
llvmFn.AddFunctionAttr(c.ctx.CreateStringAttribute("wasm-import-module", module))
name := info.importName
if name == "" {
name = info.linkName
}
llvmFn.AddFunctionAttr(c.ctx.CreateStringAttribute("wasm-import-name", name))
} }
nocaptureKind := llvm.AttributeKindID("nocapture") nocaptureKind := llvm.AttributeKindID("nocapture")
nocapture := c.ctx.CreateEnumAttribute(nocaptureKind, 0) nocapture := c.ctx.CreateEnumAttribute(nocaptureKind, 0)
+2 -2
View File
@@ -62,7 +62,7 @@ declare void @main.undefinedFunctionNotInSection(i8*) #0
attributes #0 = { "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" } attributes #0 = { "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
attributes #1 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" } attributes #1 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
attributes #2 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" "wasm-export-name"="extern_func" } attributes #2 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" "wasm-export-name"="extern_func" "wasm-import-module"="env" "wasm-import-name"="extern_func" }
attributes #3 = { inlinehint nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" } attributes #3 = { inlinehint nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
attributes #4 = { noinline nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" } attributes #4 = { noinline nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
attributes #5 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" "wasm-export-name"="exportedFunctionInSection" } attributes #5 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" "wasm-export-name"="exportedFunctionInSection" "wasm-import-module"="env" "wasm-import-name"="exportedFunctionInSection" }
+2
View File
@@ -9,8 +9,10 @@ require (
github.com/chromedp/chromedp v0.7.6 github.com/chromedp/chromedp v0.7.6
github.com/gofrs/flock v0.8.1 github.com/gofrs/flock v0.8.1
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf
github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf
github.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892 github.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892
github.com/mattn/go-colorable v0.1.8 github.com/mattn/go-colorable v0.1.8
github.com/mattn/go-tty v0.0.4
go.bug.st/serial v1.3.5 go.bug.st/serial v1.3.5
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 golang.org/x/sys v0.0.0-20220829200755-d48e67d00261
golang.org/x/tools v0.1.11 golang.org/x/tools v0.1.11
+13 -11
View File
@@ -12,7 +12,6 @@ github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moA
github.com/creack/goselect v0.1.2 h1:2DNy14+JPjRBgPzAd1thbQp4BSIihxcBf0IXhQXDRa0= github.com/creack/goselect v0.1.2 h1:2DNy14+JPjRBgPzAd1thbQp4BSIihxcBf0IXhQXDRa0=
github.com/creack/goselect v0.1.2/go.mod h1:a/NhLweNvqIYMuxcMOuWY516Cimucms3DglDzQP3hKY= github.com/creack/goselect v0.1.2/go.mod h1:a/NhLweNvqIYMuxcMOuWY516Cimucms3DglDzQP3hKY=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
@@ -23,44 +22,47 @@ github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf h1:7+FW5aGwISbqUtkfmIpZJGRgNFg2ioYPvFaUxdqpDsg= github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf h1:7+FW5aGwISbqUtkfmIpZJGRgNFg2ioYPvFaUxdqpDsg=
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf/go.mod h1:RpwtwJQFrIEPstU94h88MWPXP2ektJZ8cZ0YntAmXiE= github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf/go.mod h1:RpwtwJQFrIEPstU94h88MWPXP2ektJZ8cZ0YntAmXiE=
github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf h1:FtEj8sfIcaaBfAKrE1Cwb61YDtYq9JxChK1c7AKce7s=
github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf/go.mod h1:yrqSXGoD/4EKfF26AOGzscPOgTTJcyAwM2rpixWT+t4=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892 h1:6J+qramlHVLmiBOgRiBOnQkno8uprqG6YFFQTt6uYIw= github.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892 h1:6J+qramlHVLmiBOgRiBOnQkno8uprqG6YFFQTt6uYIw=
github.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892/go.mod h1:Pb6XcsXyropB9LNHhnqaknG/vEwYztLkQzVCHv8sQ3M= github.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892/go.mod h1:Pb6XcsXyropB9LNHhnqaknG/vEwYztLkQzVCHv8sQ3M=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-tty v0.0.4 h1:NVikla9X8MN0SQAqCYzpGyXv0jY7MNl3HOWD2dkle7E=
github.com/mattn/go-tty v0.0.4/go.mod h1:u5GGXBtZU6RQoKV8gY5W6UhMudbR5vXnUe7j3pxse28=
github.com/orisano/pixelmatch v0.0.0-20210112091706-4fa4c7ba91d5 h1:1SoBaSPudixRecmlHXb/GxmaD3fLMtHIDN13QujwQuc= github.com/orisano/pixelmatch v0.0.0-20210112091706-4fa4c7ba91d5 h1:1SoBaSPudixRecmlHXb/GxmaD3fLMtHIDN13QujwQuc=
github.com/orisano/pixelmatch v0.0.0-20210112091706-4fa4c7ba91d5/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0= github.com/orisano/pixelmatch v0.0.0-20210112091706-4fa4c7ba91d5/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
go.bug.st/serial v1.1.3 h1:YEBxJa9pKS9Wdg46B/jiaKbvvbUrjhZZZITfJHEJhaE=
go.bug.st/serial v1.1.3/go.mod h1:8TT7u/SwwNIpJ8QaG4s+HTjFt9ReXs2cdOU7ZEk50Dk=
go.bug.st/serial v1.3.5 h1:k50SqGZCnHZ2MiBQgzccXWG+kd/XpOs1jUljpDDKzaE= go.bug.st/serial v1.3.5 h1:k50SqGZCnHZ2MiBQgzccXWG+kd/XpOs1jUljpDDKzaE=
go.bug.st/serial v1.3.5/go.mod h1:z8CesKorE90Qr/oRSJiEuvzYRKol9r/anJZEb5kt304= go.bug.st/serial v1.3.5/go.mod h1:z8CesKorE90Qr/oRSJiEuvzYRKol9r/anJZEb5kt304=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0=
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 h1:v6hYoSR9T5oet+pMXwUWkbiVqx/63mlHjefrHmxwfeY= golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 h1:v6hYoSR9T5oet+pMXwUWkbiVqx/63mlHjefrHmxwfeY=
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/tools v0.1.11 h1:loJ25fNOEhSXfHrpoGj91eCUThwdNX6u24rO1xnNteY= golang.org/x/tools v0.1.11 h1:loJ25fNOEhSXfHrpoGj91eCUThwdNX6u24rO1xnNteY=
golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4= golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
tinygo.org/x/go-llvm v0.0.0-20220802112859-5bb0b77907a7 h1:nSLR52mUw7DPQQVA3ZJFH63zjU4ME84fKiin6mdnYWc= tinygo.org/x/go-llvm v0.0.0-20220802112859-5bb0b77907a7 h1:nSLR52mUw7DPQQVA3ZJFH63zjU4ME84fKiin6mdnYWc=
tinygo.org/x/go-llvm v0.0.0-20220802112859-5bb0b77907a7/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0= tinygo.org/x/go-llvm v0.0.0-20220802112859-5bb0b77907a7/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
+5
View File
@@ -369,6 +369,11 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent
nBytes := uint32(operands[3].Uint()) nBytes := uint32(operands[3].Uint())
dstObj := mem.getWritable(dst.index()) dstObj := mem.getWritable(dst.index())
dstBuf := dstObj.buffer.asRawValue(r) dstBuf := dstObj.buffer.asRawValue(r)
if mem.get(src.index()).buffer == nil {
// Looks like the source buffer is not defined.
// This can happen with //extern or //go:embed.
return nil, mem, r.errorAt(inst, errUnsupportedRuntimeInst)
}
srcBuf := mem.get(src.index()).buffer.asRawValue(r) srcBuf := mem.get(src.index()).buffer.asRawValue(r)
copy(dstBuf.buf[dst.offset():dst.offset()+nBytes], srcBuf.buf[src.offset():]) copy(dstBuf.buf[dst.offset():dst.offset()+nBytes], srcBuf.buf[src.offset():])
dstObj.buffer = dstBuf dstObj.buffer = dstBuf
+1 -1
View File
@@ -440,7 +440,7 @@ func (p *Package) parseFiles() ([]*ast.File, error) {
var initialCFlags []string var initialCFlags []string
initialCFlags = append(initialCFlags, p.program.config.CFlags()...) initialCFlags = append(initialCFlags, p.program.config.CFlags()...)
initialCFlags = append(initialCFlags, "-I"+p.Dir) initialCFlags = append(initialCFlags, "-I"+p.Dir)
generated, headerCode, cflags, ldflags, accessedFiles, errs := cgo.Process(files, p.program.workingDir, p.program.fset, initialCFlags, p.program.clangHeaders) generated, headerCode, cflags, ldflags, accessedFiles, errs := cgo.Process(files, p.program.workingDir, p.ImportPath, p.program.fset, initialCFlags, p.program.clangHeaders)
p.CFlags = append(initialCFlags, cflags...) p.CFlags = append(initialCFlags, cflags...)
p.CGoHeaders = headerCode p.CGoHeaders = headerCode
for path, hash := range accessedFiles { for path, hash := range accessedFiles {
+56 -24
View File
@@ -26,6 +26,7 @@ import (
"time" "time"
"github.com/google/shlex" "github.com/google/shlex"
"github.com/inhies/go-bytesize"
"github.com/mattn/go-colorable" "github.com/mattn/go-colorable"
"github.com/tinygo-org/tinygo/builder" "github.com/tinygo-org/tinygo/builder"
"github.com/tinygo-org/tinygo/compileopts" "github.com/tinygo-org/tinygo/compileopts"
@@ -243,17 +244,36 @@ func Test(pkgName string, stdout, stderr io.Writer, options *compileopts.Options
// Tests are always run in the package directory. // Tests are always run in the package directory.
cmd.Dir = result.MainDir cmd.Dir = result.MainDir
// Wasmtime needs a few extra flags to work. // wasmtime is the default emulator used for `-target=wasi`. wasmtime
// is a WebAssembly runtime CLI with WASI enabled by default. However,
// only stdio are allowed by default. For example, while STDOUT routes
// to the host, other files don't. It also does not inherit environment
// variables from the host. Some tests read testdata files, often from
// outside the package directory. Other tests require temporary
// writeable directories. We allow this by adding wasmtime flags below.
if config.EmulatorName() == "wasmtime" { if config.EmulatorName() == "wasmtime" {
// Add directories to the module root, but skip the current working // At this point, The current working directory is at the package
// directory which is already added by buildAndRun. // directory. Ex. $GOROOT/src/compress/flate for compress/flate.
// buildAndRun has already added arguments for wasmtime, that allow
// read-access to files such as "testdata/huffman-zero.in".
//
// Ex. main(.wasm) --dir=. -- -test.v
// Below adds additional wasmtime flags in case a test reads files
// outside its directory, like "../testdata/e.txt". This allows any
// relative directory up to the module root, even if the test never
// reads any files.
//
// Ex. --dir=.. --dir=../.. --dir=../../..
dirs := dirsToModuleRoot(result.MainDir, result.ModuleRoot) dirs := dirsToModuleRoot(result.MainDir, result.ModuleRoot)
var args []string var args []string
for _, d := range dirs[1:] { for _, d := range dirs[1:] {
args = append(args, "--dir="+d) args = append(args, "--dir="+d)
} }
// create a new temp directory just for this run, announce it to os.TempDir() via TMPDIR // Some tests create temp directories using os.MkdirTemp or via
// t.TempDir(). Create a writeable directory and map it to the
// default tempDir environment variable: TMPDIR.
tmpdir, err := os.MkdirTemp("", "tinygotmp") tmpdir, err := os.MkdirTemp("", "tinygotmp")
if err != nil { if err != nil {
return fmt.Errorf("failed to create temporary directory: %w", err) return fmt.Errorf("failed to create temporary directory: %w", err)
@@ -262,7 +282,8 @@ func Test(pkgName string, stdout, stderr io.Writer, options *compileopts.Options
// TODO: add option to not delete temp dir for debugging? // TODO: add option to not delete temp dir for debugging?
defer os.RemoveAll(tmpdir) defer os.RemoveAll(tmpdir)
// Insert new argments at the front of the command line argments. // The below re-organizes the arguments so that the current
// directory is added last.
args = append(args, cmd.Args[1:]...) args = append(args, cmd.Args[1:]...)
cmd.Args = append(cmd.Args[:1:1], args...) cmd.Args = append(cmd.Args[:1:1], args...)
} }
@@ -402,7 +423,6 @@ func Flash(pkgName, port string, options *compileopts.Options) error {
if err != nil { if err != nil {
return &commandError{"failed to flash", result.Binary, err} return &commandError{"failed to flash", result.Binary, err}
} }
return nil
case "msd": case "msd":
switch fileExt { switch fileExt {
case ".uf2": case ".uf2":
@@ -410,13 +430,11 @@ func Flash(pkgName, port string, options *compileopts.Options) error {
if err != nil { if err != nil {
return &commandError{"failed to flash", result.Binary, err} return &commandError{"failed to flash", result.Binary, err}
} }
return nil
case ".hex": case ".hex":
err := flashHexUsingMSD(config.Target.FlashVolume, result.Binary, config.Options) err := flashHexUsingMSD(config.Target.FlashVolume, result.Binary, config.Options)
if err != nil { if err != nil {
return &commandError{"failed to flash", result.Binary, err} return &commandError{"failed to flash", result.Binary, err}
} }
return nil
default: default:
return errors.New("mass storage device flashing currently only supports uf2 and hex") return errors.New("mass storage device flashing currently only supports uf2 and hex")
} }
@@ -437,7 +455,6 @@ func Flash(pkgName, port string, options *compileopts.Options) error {
if err != nil { if err != nil {
return &commandError{"failed to flash", result.Binary, err} return &commandError{"failed to flash", result.Binary, err}
} }
return nil
case "bmp": case "bmp":
gdb, err := config.Target.LookupGDB() gdb, err := config.Target.LookupGDB()
if err != nil { if err != nil {
@@ -456,10 +473,13 @@ func Flash(pkgName, port string, options *compileopts.Options) error {
if err != nil { if err != nil {
return &commandError{"failed to flash", result.Binary, err} return &commandError{"failed to flash", result.Binary, err}
} }
return nil
default: default:
return fmt.Errorf("unknown flash method: %s", flashMethod) return fmt.Errorf("unknown flash method: %s", flashMethod)
} }
if options.Monitor {
return Monitor("", options)
}
return nil
}) })
} }
@@ -978,7 +998,8 @@ func getDefaultPort(portFlag string, usbInterfaces []string) (port string, err e
preferredPortIDs = append(preferredPortIDs, [2]uint16{uint16(vid), uint16(pid)}) preferredPortIDs = append(preferredPortIDs, [2]uint16{uint16(vid), uint16(pid)})
} }
var primaryPorts []string // ports picked from preferred USB VID/PID var primaryPorts []string // ports picked from preferred USB VID/PID
var secondaryPorts []string // other ports (as a fallback)
for _, p := range portsList { for _, p := range portsList {
if !p.IsUSB { if !p.IsUSB {
continue continue
@@ -1000,6 +1021,8 @@ func getDefaultPort(portFlag string, usbInterfaces []string) (port string, err e
continue continue
} }
} }
secondaryPorts = append(secondaryPorts, p.Name)
} }
if len(primaryPorts) == 1 { if len(primaryPorts) == 1 {
// There is exactly one match in the set of preferred ports. Use // There is exactly one match in the set of preferred ports. Use
@@ -1011,18 +1034,10 @@ func getDefaultPort(portFlag string, usbInterfaces []string) (port string, err e
// one device of the same type are connected (e.g. two Arduino // one device of the same type are connected (e.g. two Arduino
// Unos). // Unos).
ports = primaryPorts ports = primaryPorts
} } else {
// No preferred ports found. Fall back to other serial ports
if len(ports) == 0 { // available in the system.
// fallback ports = secondaryPorts
switch runtime.GOOS {
case "darwin":
ports, err = filepath.Glob("/dev/cu.usb*")
case "linux":
ports, err = filepath.Glob("/dev/ttyACM*")
case "windows":
ports, err = serial.GetPortsList()
}
} }
default: default:
return "", errors.New("unable to search for a default USB device to be flashed on this OS") return "", errors.New("unable to search for a default USB device to be flashed on this OS")
@@ -1037,7 +1052,9 @@ func getDefaultPort(portFlag string, usbInterfaces []string) (port string, err e
} }
if len(portCandidates) == 0 { if len(portCandidates) == 0 {
if len(ports) == 1 { if len(usbInterfaces) > 0 {
return "", errors.New("unable to search for a default USB device - use -port flag, available ports are " + strings.Join(ports, ", "))
} else if len(ports) == 1 {
return ports[0], nil return ports[0], nil
} else { } else {
return "", errors.New("multiple serial ports available - use -port flag, available ports are " + strings.Join(ports, ", ")) return "", errors.New("multiple serial ports available - use -port flag, available ports are " + strings.Join(ports, ", "))
@@ -1102,6 +1119,7 @@ func usage(command string) {
fmt.Fprintln(os.Stderr, " flash: compile and flash to the device") fmt.Fprintln(os.Stderr, " flash: compile and flash to the device")
fmt.Fprintln(os.Stderr, " gdb: run/flash and immediately enter GDB") fmt.Fprintln(os.Stderr, " gdb: run/flash and immediately enter GDB")
fmt.Fprintln(os.Stderr, " lldb: run/flash and immediately enter LLDB") fmt.Fprintln(os.Stderr, " lldb: run/flash and immediately enter LLDB")
fmt.Fprintln(os.Stderr, " monitor: open communication port")
fmt.Fprintln(os.Stderr, " env: list environment variables used during build") fmt.Fprintln(os.Stderr, " env: list environment variables used during build")
fmt.Fprintln(os.Stderr, " list: run go list using the TinyGo root") fmt.Fprintln(os.Stderr, " list: run go list using the TinyGo root")
fmt.Fprintln(os.Stderr, " clean: empty cache directory ("+goenv.Get("GOCACHE")+")") fmt.Fprintln(os.Stderr, " clean: empty cache directory ("+goenv.Get("GOCACHE")+")")
@@ -1298,6 +1316,12 @@ func main() {
var tags buildutil.TagsFlag var tags buildutil.TagsFlag
flag.Var(&tags, "tags", "a space-separated list of extra build tags") flag.Var(&tags, "tags", "a space-separated list of extra build tags")
target := flag.String("target", "", "chip/board name or JSON target specification file") target := flag.String("target", "", "chip/board name or JSON target specification file")
var stackSize uint64
flag.Func("stack-size", "goroutine stack size (if unknown at compile time)", func(s string) error {
size, err := bytesize.Parse(s)
stackSize = uint64(size)
return err
})
printSize := flag.String("size", "", "print sizes (none, short, full)") printSize := flag.String("size", "", "print sizes (none, short, full)")
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")
@@ -1312,6 +1336,8 @@ 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")
cpuprofile := flag.String("cpuprofile", "", "cpuprofile output") cpuprofile := flag.String("cpuprofile", "", "cpuprofile output")
monitor := flag.Bool("monitor", false, "enable serial monitor")
baudrate := flag.Int("baudrate", 115200, "baudrate of serial monitor")
var flagJSON, flagDeps, flagTest bool var flagJSON, flagDeps, flagTest bool
if command == "help" || command == "list" || command == "info" || command == "build" { if command == "help" || command == "list" || command == "info" || command == "build" {
@@ -1378,6 +1404,7 @@ func main() {
GOARCH: goenv.Get("GOARCH"), GOARCH: goenv.Get("GOARCH"),
GOARM: goenv.Get("GOARM"), GOARM: goenv.Get("GOARM"),
Target: *target, Target: *target,
StackSize: stackSize,
Opt: *opt, Opt: *opt,
GC: *gc, GC: *gc,
PanicStrategy: *panicStrategy, PanicStrategy: *panicStrategy,
@@ -1400,6 +1427,8 @@ func main() {
OpenOCDCommands: ocdCommands, OpenOCDCommands: ocdCommands,
LLVMFeatures: *llvmFeatures, LLVMFeatures: *llvmFeatures,
PrintJSON: flagJSON, PrintJSON: flagJSON,
Monitor: *monitor,
BaudRate: *baudrate,
} }
if *printCommands { if *printCommands {
options.PrintCommands = printCommand options.PrintCommands = printCommand
@@ -1590,6 +1619,9 @@ func main() {
fmt.Println("FAIL") fmt.Println("FAIL")
os.Exit(1) os.Exit(1)
} }
case "monitor":
err := Monitor(*port, options)
handleCompilerError(err)
case "targets": case "targets":
dir := filepath.Join(goenv.Get("TINYGOROOT"), "targets") dir := filepath.Join(goenv.Get("TINYGOROOT"), "targets")
entries, err := ioutil.ReadDir(dir) entries, err := ioutil.ReadDir(dir)
+106
View File
@@ -0,0 +1,106 @@
package main
import (
"fmt"
"os"
"os/signal"
"time"
"github.com/mattn/go-tty"
"github.com/tinygo-org/tinygo/builder"
"github.com/tinygo-org/tinygo/compileopts"
"go.bug.st/serial"
)
// Monitor connects to the given port and reads/writes the serial port.
func Monitor(port string, options *compileopts.Options) error {
config, err := builder.NewConfig(options)
if err != nil {
return err
}
wait := 300
for i := 0; i <= wait; i++ {
port, err = getDefaultPort(port, config.Target.SerialPort)
if err != nil {
if i < wait {
time.Sleep(10 * time.Millisecond)
continue
}
return err
}
break
}
br := options.BaudRate
if br <= 0 {
br = 115200
}
wait = 300
var p serial.Port
for i := 0; i <= wait; i++ {
p, err = serial.Open(port, &serial.Mode{BaudRate: br})
if err != nil {
if i < wait {
time.Sleep(10 * time.Millisecond)
continue
}
return err
}
break
}
defer p.Close()
tty, err := tty.Open()
if err != nil {
return err
}
defer tty.Close()
sig := make(chan os.Signal, 1)
signal.Notify(sig, os.Interrupt)
defer signal.Stop(sig)
go func() {
<-sig
tty.Close()
os.Exit(0)
}()
fmt.Printf("Connected to %s. Press Ctrl-C to exit.\n", port)
errCh := make(chan error, 1)
go func() {
buf := make([]byte, 100*1024)
for {
n, err := p.Read(buf)
if err != nil {
errCh <- fmt.Errorf("read error: %w", err)
return
}
if n == 0 {
continue
}
fmt.Printf("%v", string(buf[:n]))
}
}()
go func() {
for {
r, err := tty.ReadRune()
if err != nil {
errCh <- err
return
}
if r == 0 {
continue
}
p.Write([]byte(string(r)))
}
}()
return <-errCh
}
+2 -2
View File
@@ -1,5 +1,5 @@
//go:build stm32 || (sam && atsamd51) || (sam && atsame5x) //go:build nrf || stm32 || (sam && atsamd51) || (sam && atsame5x)
// +build stm32 sam,atsamd51 sam,atsame5x // +build nrf stm32 sam,atsamd51 sam,atsame5x
package rand package rand
-49
View File
@@ -1,49 +0,0 @@
// Reads multiple rp2040 ADC channels concurrently. Including the internal temperature sensor
package main
import (
"fmt"
"machine"
"time"
)
type celsius float32
func (c celsius) String() string {
return fmt.Sprintf("%4.1f℃", c)
}
// rp2040 ADC is 12 bits. Reading are shifted <<4 to fill the 16-bit range.
var adcReading [3]uint16
func readADC(a machine.ADC, w time.Duration, i int) {
for {
adcReading[i] = a.Get()
time.Sleep(w)
}
}
func main() {
machine.InitADC()
a0 := machine.ADC{machine.ADC0} // GPIO26 input
a1 := machine.ADC{machine.ADC1} // GPIO27 input
a2 := machine.ADC{machine.ADC2} // GPIO28 input
t := machine.ADC_TEMP_SENSOR // Internal Temperature sensor
// Configure sets the GPIOs to PinAnalog mode
a0.Configure(machine.ADCConfig{})
a1.Configure(machine.ADCConfig{})
a2.Configure(machine.ADCConfig{})
// Configure powers on the temperature sensor
t.Configure(machine.ADCConfig{})
// Safe to read concurrently
go readADC(a0, 10*time.Millisecond, 0)
go readADC(a1, 17*time.Millisecond, 1)
go readADC(a2, 29*time.Millisecond, 2)
for {
fmt.Printf("ADC0: %5d ADC1: %5d ADC2: %5d Temp: %v\n\r", adcReading[0], adcReading[1], adcReading[2], celsius(float32(t.ReadTemperature())/1000))
time.Sleep(1000 * time.Millisecond)
}
}
+23
View File
@@ -0,0 +1,23 @@
// Read the internal temperature sensor of the chip.
package main
import (
"fmt"
"machine"
"time"
)
type celsius float32
func (c celsius) String() string {
return fmt.Sprintf("%4.1f℃", c)
}
func main() {
for {
temp := celsius(float32(machine.ReadTemperature()) / 1000)
println("temperature:", temp.String())
time.Sleep(time.Second)
}
}
+9 -11
View File
@@ -21,12 +21,14 @@ $ tinygo build -o ./wasm.wasm -target wasm ./main/main.go
This creates a `wasm.wasm` file, which we can load in JavaScript and execute in This creates a `wasm.wasm` file, which we can load in JavaScript and execute in
a browser. a browser.
This examples folder contains two examples that can be built using `make`: Next, choose which example you want to use:
* [callback](callback): Defines and configures callbacks in Wasm.
```bash * [export](export): Defines callbacks in Wasm, but configures them in JavaScript.
$ make export * [invoke](invoke): Invokes a function defined in JavaScript from Wasm.
``` * [main](main): Prints a message to the JavaScript console from Wasm.
* [slices](slices): Splits an Array defined in JavaScript from Wasm.
Let's say you chose [main](main), you'd build it like so:
```bash ```bash
$ make main $ make main
``` ```
@@ -42,12 +44,8 @@ Serving ./html on http://localhost:8080
Use your web browser to visit http://localhost:8080. Use your web browser to visit http://localhost:8080.
* The wasm "export" example displays a simple math equation using HTML, with * Tip: Open the browser development tools (e.g. Right-click, Inspect in
the result calculated dynamically using WebAssembly. Changing any of the FireFox) to see console output.
values on the left hand side triggers the exported wasm `update` function to
recalculate the result.
* The wasm "main" example uses `println` to write to your browser JavaScript
console. You may need to open the browser development tools console to see it.
## How it works ## How it works
+2
View File
@@ -8,10 +8,12 @@ import (
var a, b int var a, b int
func main() { func main() {
wait := make(chan struct{}, 0)
document := js.Global().Get("document") document := js.Global().Get("document")
document.Call("getElementById", "a").Set("oninput", updater(&a)) document.Call("getElementById", "a").Set("oninput", updater(&a))
document.Call("getElementById", "b").Set("oninput", updater(&b)) document.Call("getElementById", "b").Set("oninput", updater(&b))
update() update()
<-wait
} }
func updater(n *int) js.Func { func updater(n *int) js.Func {
+4
View File
@@ -2,12 +2,16 @@
.functype start_unwind (i32) -> () .functype start_unwind (i32) -> ()
.import_module start_unwind, asyncify .import_module start_unwind, asyncify
.import_name start_unwind, start_unwind
.functype stop_unwind () -> () .functype stop_unwind () -> ()
.import_module stop_unwind, asyncify .import_module stop_unwind, asyncify
.import_name stop_unwind, stop_unwind
.functype start_rewind (i32) -> () .functype start_rewind (i32) -> ()
.import_module start_rewind, asyncify .import_module start_rewind, asyncify
.import_name start_rewind, start_rewind
.functype stop_rewind () -> () .functype stop_rewind () -> ()
.import_module stop_rewind, asyncify .import_module stop_rewind, asyncify
.import_name stop_rewind, stop_rewind
.global tinygo_unwind .global tinygo_unwind
.hidden tinygo_unwind .hidden tinygo_unwind
+28 -2
View File
@@ -1,5 +1,8 @@
// Windows on amd64 has a slightly different ABI than other (*nix) systems. // Windows on amd64 has a slightly different ABI than other (*nix) systems.
// Therefore, assembly functions need to be tweaked slightly. // Therefore, assembly functions need to be tweaked slightly.
//
// The calling convention is described here:
// https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170
.section .text.tinygo_startTask,"ax" .section .text.tinygo_startTask,"ax"
.global tinygo_startTask .global tinygo_startTask
@@ -17,8 +20,9 @@ tinygo_startTask:
// Branch to the "goroutine start" function. // Branch to the "goroutine start" function.
callq *%r12 callq *%r12
// After return, exit this goroutine. This is a tail call. // After return, exit this goroutine.
jmp tinygo_pause // This has to be a call, not a jump, to keep the stack correctly aligned.
callq tinygo_pause
.global tinygo_swapTask .global tinygo_swapTask
.section .text.tinygo_swapTask,"ax" .section .text.tinygo_swapTask,"ax"
@@ -35,6 +39,17 @@ tinygo_swapTask:
pushq %rsi pushq %rsi
pushq %rdi pushq %rdi
pushq %rbp pushq %rbp
sub $160, %rsp
movaps %xmm6, 144(%rsp)
movaps %xmm7, 128(%rsp)
movaps %xmm8, 112(%rsp)
movaps %xmm9, 96(%rsp)
movaps %xmm10, 80(%rsp)
movaps %xmm11, 64(%rsp)
movaps %xmm12, 48(%rsp)
movaps %xmm13, 32(%rsp)
movaps %xmm14, 16(%rsp)
movaps %xmm15, 0(%rsp)
pushq %rbx pushq %rbx
// Save the current stack pointer in oldStack. // Save the current stack pointer in oldStack.
@@ -45,6 +60,17 @@ tinygo_swapTask:
// Load saved register from the new stack. // Load saved register from the new stack.
popq %rbx popq %rbx
movaps 0(%rsp), %xmm15
movaps 16(%rsp), %xmm14
movaps 32(%rsp), %xmm13
movaps 48(%rsp), %xmm12
movaps 64(%rsp), %xmm11
movaps 80(%rsp), %xmm10
movaps 96(%rsp), %xmm9
movaps 112(%rsp), %xmm8
movaps 128(%rsp), %xmm7
movaps 144(%rsp), %xmm6
add $160, %rsp
popq %rbp popq %rbp
popq %rdi popq %rdi
popq %rsi popq %rsi
+27 -8
View File
@@ -13,15 +13,34 @@ var systemStack uintptr
// calleeSavedRegs is the list of registers that must be saved and restored when // calleeSavedRegs is the list of registers that must be saved and restored when
// switching between tasks. Also see task_stack_amd64_windows.S that relies on // switching between tasks. Also see task_stack_amd64_windows.S that relies on
// the exact layout of this struct. // the exact layout of this struct.
// The calling convention is described here:
// https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170
// Most importantly, these are the registers we need to save/restore:
//
// > The x64 ABI considers registers RBX, RBP, RDI, RSI, RSP, R12, R13, R14,
// > R15, and XMM6-XMM15 nonvolatile. They must be saved and restored by a
// > function that uses them.
type calleeSavedRegs struct { type calleeSavedRegs struct {
rbx uintptr // Note: rbx is placed here so that the stack is correctly aligned when
rbp uintptr // loading/storing the xmm registers.
rdi uintptr rbx uintptr
rsi uintptr xmm15 [2]uint64
r12 uintptr xmm14 [2]uint64
r13 uintptr xmm13 [2]uint64
r14 uintptr xmm12 [2]uint64
r15 uintptr xmm11 [2]uint64
xmm10 [2]uint64
xmm9 [2]uint64
xmm8 [2]uint64
xmm7 [2]uint64
xmm6 [2]uint64
rbp uintptr
rdi uintptr
rsi uintptr
r12 uintptr
r13 uintptr
r14 uintptr
r15 uintptr
pc uintptr pc uintptr
} }
+1 -1
View File
@@ -7,7 +7,7 @@
package machine package machine
// used to reset into bootloader // used to reset into bootloader
const RESET_MAGIC_VALUE = 0x07738135 const resetMagicValue = 0x07738135
// GPIO Pins // GPIO Pins
const ( const (
+1 -1
View File
@@ -7,7 +7,7 @@
package machine package machine
// used to reset into bootloader // used to reset into bootloader
const RESET_MAGIC_VALUE = 0x07738135 const resetMagicValue = 0x07738135
// GPIO Pins // GPIO Pins
const ( const (
+1 -1
View File
@@ -7,7 +7,7 @@
package machine package machine
// used to reset into bootloader // used to reset into bootloader
const RESET_MAGIC_VALUE = 0x07738135 const resetMagicValue = 0x07738135
// GPIO Pins // GPIO Pins
const ( const (
+1 -1
View File
@@ -4,7 +4,7 @@
package machine package machine
// used to reset into bootloader // used to reset into bootloader
const RESET_MAGIC_VALUE = 0x07738135 const resetMagicValue = 0x07738135
// GPIO Pins - Digital Low // GPIO Pins - Digital Low
const ( const (
+6 -6
View File
@@ -12,9 +12,9 @@ const (
const ( const (
PB0 = portB + 0 PB0 = portB + 0
PB1 = portB + 1 PB1 = portB + 1 // peripherals: Timer1 channel A
PB2 = portB + 2 PB2 = portB + 2 // peripherals: Timer1 channel B
PB3 = portB + 3 PB3 = portB + 3 // peripherals: Timer2 channel A
PB4 = portB + 4 PB4 = portB + 4
PB5 = portB + 5 PB5 = portB + 5
PB6 = portB + 6 PB6 = portB + 6
@@ -30,9 +30,9 @@ const (
PD0 = portD + 0 PD0 = portD + 0
PD1 = portD + 1 PD1 = portD + 1
PD2 = portD + 2 PD2 = portD + 2
PD3 = portD + 3 PD3 = portD + 3 // peripherals: Timer2 channel B
PD4 = portD + 4 PD4 = portD + 4
PD5 = portD + 5 PD5 = portD + 5 // peripherals: Timer0 channel B
PD6 = portD + 6 PD6 = portD + 6 // peripherals: Timer0 channel A
PD7 = portD + 7 PD7 = portD + 7
) )
+34 -34
View File
@@ -10,38 +10,38 @@ func CPUFrequency() uint32 {
// Hardware pins // Hardware pins
const ( const (
PA00 Pin = 0 PA00 Pin = 0 // peripherals: TCC2 channel 0
PA01 Pin = 1 PA01 Pin = 1 // peripherals: TCC2 channel 1
PA02 Pin = 2 PA02 Pin = 2
PA03 Pin = 3 PA03 Pin = 3
PA04 Pin = 4 PA04 Pin = 4 // peripherals: TCC0 channel 0
PA05 Pin = 5 PA05 Pin = 5 // peripherals: TCC0 channel 1
PA06 Pin = 6 PA06 Pin = 6 // peripherals: TCC1 channel 0
PA07 Pin = 7 PA07 Pin = 7 // peripherals: TCC1 channel 1
PA08 Pin = 8 PA08 Pin = 8 // peripherals: TCC0 channel 0, TCC1 channel 2
PA09 Pin = 9 PA09 Pin = 9 // peripherals: TCC0 channel 1, TCC1 channel 3
PA10 Pin = 10 PA10 Pin = 10 // peripherals: TCC1 channel 0, TCC0 channel 2
PA11 Pin = 11 PA11 Pin = 11 // peripherals: TCC1 channel 1, TCC0 channel 3
PA12 Pin = 12 PA12 Pin = 12 // peripherals: TCC2 channel 0, TCC0 channel 2
PA13 Pin = 13 PA13 Pin = 13 // peripherals: TCC2 channel 1, TCC0 channel 3
PA14 Pin = 14 PA14 Pin = 14 // peripherals: TCC0 channel 0
PA15 Pin = 15 PA15 Pin = 15 // peripherals: TCC0 channel 1
PA16 Pin = 16 PA16 Pin = 16 // peripherals: TCC2 channel 0, TCC0 channel 2
PA17 Pin = 17 PA17 Pin = 17 // peripherals: TCC2 channel 1, TCC0 channel 3
PA18 Pin = 18 PA18 Pin = 18 // peripherals: TCC0 channel 2
PA19 Pin = 19 PA19 Pin = 19 // peripherals: TCC0 channel 3
PA20 Pin = 20 PA20 Pin = 20 // peripherals: TCC0 channel 2
PA21 Pin = 21 PA21 Pin = 21 // peripherals: TCC0 channel 3
PA22 Pin = 22 PA22 Pin = 22 // peripherals: TCC0 channel 0
PA23 Pin = 23 PA23 Pin = 23 // peripherals: TCC0 channel 1
PA24 Pin = 24 PA24 Pin = 24 // peripherals: TCC1 channel 2
PA25 Pin = 25 PA25 Pin = 25 // peripherals: TCC1 channel 3
PA26 Pin = 26 PA26 Pin = 26
PA27 Pin = 27 PA27 Pin = 27
PA28 Pin = 28 PA28 Pin = 28
PA29 Pin = 29 PA29 Pin = 29
PA30 Pin = 30 PA30 Pin = 30 // peripherals: TCC1 channel 0
PA31 Pin = 31 PA31 Pin = 31 // peripherals: TCC1 channel 1
PB00 Pin = 32 PB00 Pin = 32
PB01 Pin = 33 PB01 Pin = 33
PB02 Pin = 34 PB02 Pin = 34
@@ -52,14 +52,14 @@ const (
PB07 Pin = 39 PB07 Pin = 39
PB08 Pin = 40 PB08 Pin = 40
PB09 Pin = 41 PB09 Pin = 41
PB10 Pin = 42 PB10 Pin = 42 // peripherals: TCC0 channel 0
PB11 Pin = 43 PB11 Pin = 43 // peripherals: TCC0 channel 1
PB12 Pin = 44 PB12 Pin = 44 // peripherals: TCC0 channel 2
PB13 Pin = 45 PB13 Pin = 45 // peripherals: TCC0 channel 3
PB14 Pin = 46 PB14 Pin = 46
PB15 Pin = 47 PB15 Pin = 47
PB16 Pin = 48 PB16 Pin = 48 // peripherals: TCC0 channel 0
PB17 Pin = 49 PB17 Pin = 49 // peripherals: TCC0 channel 1
PB18 Pin = 50 PB18 Pin = 50
PB19 Pin = 51 PB19 Pin = 51
PB20 Pin = 52 PB20 Pin = 52
@@ -72,6 +72,6 @@ const (
PB27 Pin = 59 PB27 Pin = 59
PB28 Pin = 60 PB28 Pin = 60
PB29 Pin = 61 PB29 Pin = 61
PB30 Pin = 62 PB30 Pin = 62 // peripherals: TCC0 channel 0, TCC1 channel 2
PB31 Pin = 63 PB31 Pin = 63 // peripherals: TCC0 channel 1, TCC1 channel 3
) )
+1 -1
View File
@@ -8,7 +8,7 @@ import (
) )
// Definition for compatibility, but not used // Definition for compatibility, but not used
const RESET_MAGIC_VALUE = 0x00000000 const resetMagicValue = 0x00000000
const ( const (
LED = PC18 LED = PC18
+1 -1
View File
@@ -4,7 +4,7 @@
package machine package machine
// used to reset into bootloader // used to reset into bootloader
const RESET_MAGIC_VALUE = 0xf01669ef const resetMagicValue = 0xf01669ef
// GPIO Pins // GPIO Pins
const ( const (
+1 -1
View File
@@ -4,7 +4,7 @@
package machine package machine
// used to reset into bootloader // used to reset into bootloader
const RESET_MAGIC_VALUE = 0xf01669ef const resetMagicValue = 0xf01669ef
// GPIO Pins // GPIO Pins
const ( const (
+1 -1
View File
@@ -8,7 +8,7 @@ import (
) )
// used to reset into bootloader // used to reset into bootloader
const RESET_MAGIC_VALUE = 0xf01669ef const resetMagicValue = 0xf01669ef
// GPIO Pins // GPIO Pins
const ( const (
+1 -1
View File
@@ -4,7 +4,7 @@
package machine package machine
// used to reset into bootloader // used to reset into bootloader
const RESET_MAGIC_VALUE = 0xf01669ef const resetMagicValue = 0xf01669ef
// GPIO Pins // GPIO Pins
const ( const (
+1 -1
View File
@@ -245,7 +245,7 @@ const (
// Other peripheral constants // Other peripheral constants
const ( const (
RESET_MAGIC_VALUE = 0xF01669EF // Used to reset into bootloader resetMagicValue = 0xF01669EF // Used to reset into bootloader
) )
// USB CDC pins // USB CDC pins
+1 -1
View File
@@ -4,7 +4,7 @@
package machine package machine
// used to reset into bootloader // used to reset into bootloader
const RESET_MAGIC_VALUE = 0xf01669ef const resetMagicValue = 0xf01669ef
// GPIO Pins // GPIO Pins
const ( const (
+1 -1
View File
@@ -4,7 +4,7 @@
package machine package machine
// used to reset into bootloader // used to reset into bootloader
const RESET_MAGIC_VALUE = 0xf01669ef const resetMagicValue = 0xf01669ef
// GPIO Pins // GPIO Pins
const ( const (
+1 -1
View File
@@ -4,7 +4,7 @@
package machine package machine
// used to reset into bootloader // used to reset into bootloader
const RESET_MAGIC_VALUE = 0xF01669EF const resetMagicValue = 0xF01669EF
// Digital pins // Digital pins
const ( const (
+1 -1
View File
@@ -4,7 +4,7 @@
package machine package machine
// used to reset into bootloader // used to reset into bootloader
const RESET_MAGIC_VALUE = 0xf01669ef const resetMagicValue = 0xf01669ef
// GPIO Pins // GPIO Pins
const ( const (
+1 -1
View File
@@ -7,7 +7,7 @@
package machine package machine
// used to reset into bootloader // used to reset into bootloader
const RESET_MAGIC_VALUE = 0x07738135 const resetMagicValue = 0x07738135
// Note: On the P1AM-100, pins D8, D9, D10, A3, and A4 are used for // Note: On the P1AM-100, pins D8, D9, D10, A3, and A4 are used for
// communication with the base controller. // communication with the base controller.
+1 -1
View File
@@ -4,7 +4,7 @@
package machine package machine
// used to reset into bootloader // used to reset into bootloader
const RESET_MAGIC_VALUE = 0xf01669ef const resetMagicValue = 0xf01669ef
// GPIO Pins // GPIO Pins
const ( const (
+1 -1
View File
@@ -4,7 +4,7 @@
package machine package machine
// used to reset into bootloader // used to reset into bootloader
const RESET_MAGIC_VALUE = 0xf01669ef const resetMagicValue = 0xf01669ef
// GPIO Pins // GPIO Pins
const ( const (
+1 -1
View File
@@ -4,7 +4,7 @@
package machine package machine
// used to reset into bootloader // used to reset into bootloader
const RESET_MAGIC_VALUE = 0xf01669ef const resetMagicValue = 0xf01669ef
// GPIO Pins // GPIO Pins
const ( const (
+1 -1
View File
@@ -4,7 +4,7 @@
package machine package machine
// used to reset into bootloader // used to reset into bootloader
const RESET_MAGIC_VALUE = 0xf01669ef const resetMagicValue = 0xf01669ef
// GPIO Pins // GPIO Pins
const ( const (
+4 -5
View File
@@ -36,10 +36,9 @@ const (
) )
const ( const (
NEOPIXELS = GPIO12 NEOPIXEL = GPIO12
WS2812 = GPIO12 WS2812 = GPIO12
NEOPIXELS_POWER = GPIO11 NEOPIXEL_POWER = GPIO11
LED = GPIO20
) )
// I2C Pins. // I2C Pins.
@@ -116,5 +115,5 @@ const (
var ( var (
usb_VID uint16 = 0x239A usb_VID uint16 = 0x239A
usb_PID uint16 = 0x80F1 usb_PID uint16 = 0x80F7
) )
+1 -1
View File
@@ -4,7 +4,7 @@
package machine package machine
// used to reset into bootloader // used to reset into bootloader
const RESET_MAGIC_VALUE = 0xf01669ef const resetMagicValue = 0xf01669ef
// GPIO Pins // GPIO Pins
const ( const (
+1 -1
View File
@@ -4,7 +4,7 @@
package machine package machine
// used to reset into bootloader // used to reset into bootloader
const RESET_MAGIC_VALUE = 0xf01669ef const resetMagicValue = 0xf01669ef
const ( const (
ADC0 = A0 ADC0 = A0
+1 -1
View File
@@ -104,7 +104,7 @@ const (
var ( var (
usb_VID uint16 = 0x2886 usb_VID uint16 = 0x2886
usb_PID uint16 = 0x0045 usb_PID uint16 = 0x8045
) )
var ( var (
+1 -1
View File
@@ -4,7 +4,7 @@
package machine package machine
// used to reset into bootloader // used to reset into bootloader
const RESET_MAGIC_VALUE = 0xf01669ef const resetMagicValue = 0xf01669ef
// GPIO Pins // GPIO Pins
const ( const (
+2
View File
@@ -8,6 +8,8 @@ import (
) )
// TWI_FREQ is the I2C bus speed. Normally either 100 kHz, or 400 kHz for high-speed bus. // TWI_FREQ is the I2C bus speed. Normally either 100 kHz, or 400 kHz for high-speed bus.
//
// Deprecated: use 100 * machine.KHz or 400 * machine.KHz instead.
const ( const (
TWI_FREQ_100KHZ = 100000 TWI_FREQ_100KHZ = 100000
TWI_FREQ_400KHZ = 400000 TWI_FREQ_400KHZ = 400000
+7
View File
@@ -18,6 +18,13 @@ var (
// particular chip but instead runs in WebAssembly for example. // particular chip but instead runs in WebAssembly for example.
const Device = deviceName const Device = deviceName
// Generic constants.
const (
KHz = 1000
MHz = 1000_000
GHz = 1000_000_000
)
// PinMode sets the direction and pull mode of the pin. For example, PinOutput // PinMode sets the direction and pull mode of the pin. For example, PinOutput
// sets the pin as an output and PinInputPullup sets the pin as an input with a // sets the pin as an output and PinInputPullup sets the pin as an input with a
// pull-up. // pull-up.
+1 -1
View File
@@ -26,7 +26,7 @@ type I2CConfig struct {
func (i2c *I2C) Configure(config I2CConfig) error { func (i2c *I2C) Configure(config I2CConfig) error {
// Default I2C bus speed is 100 kHz. // Default I2C bus speed is 100 kHz.
if config.Frequency == 0 { if config.Frequency == 0 {
config.Frequency = TWI_FREQ_100KHZ config.Frequency = 100 * KHz
} }
// Activate internal pullups for twi. // Activate internal pullups for twi.
+15 -15
View File
@@ -38,10 +38,10 @@ const (
PB1 = portB + 1 PB1 = portB + 1
PB2 = portB + 2 PB2 = portB + 2
PB3 = portB + 3 PB3 = portB + 3
PB4 = portB + 4 PB4 = portB + 4 // peripherals: Timer2 channel A
PB5 = portB + 5 PB5 = portB + 5 // peripherals: Timer1 channel A
PB6 = portB + 6 PB6 = portB + 6 // peripherals: Timer1 channel B
PB7 = portB + 7 PB7 = portB + 7 // peripherals: Timer0 channel A
PC0 = portC + 0 PC0 = portC + 0
PC1 = portC + 1 PC1 = portC + 1
PC2 = portC + 2 PC2 = portC + 2
@@ -57,9 +57,9 @@ const (
PD7 = portD + 7 PD7 = portD + 7
PE0 = portE + 0 PE0 = portE + 0
PE1 = portE + 1 PE1 = portE + 1
PE3 = portE + 3 PE3 = portE + 3 // peripherals: Timer3 channel A
PE4 = portE + 4 PE4 = portE + 4 // peripherals: Timer3 channel B
PE5 = portE + 5 PE5 = portE + 5 // peripherals: Timer3 channel C
PE6 = portE + 6 PE6 = portE + 6
PF0 = portF + 0 PF0 = portF + 0
PF1 = portF + 1 PF1 = portF + 1
@@ -72,13 +72,13 @@ const (
PG0 = portG + 0 PG0 = portG + 0
PG1 = portG + 1 PG1 = portG + 1
PG2 = portG + 2 PG2 = portG + 2
PG5 = portG + 5 PG5 = portG + 5 // peripherals: Timer0 channel B
PH0 = portH + 0 PH0 = portH + 0
PH1 = portH + 1 PH1 = portH + 1
PH3 = portH + 3 PH3 = portH + 3 // peripherals: Timer4 channel A
PH4 = portH + 4 PH4 = portH + 4 // peripherals: Timer4 channel B
PH5 = portH + 5 PH5 = portH + 5 // peripherals: Timer4 channel C
PH6 = portH + 6 PH6 = portH + 6 // peripherals: Timer0 channel B
PJ0 = portJ + 0 PJ0 = portJ + 0
PJ1 = portJ + 1 PJ1 = portJ + 1
PK0 = portK + 0 PK0 = portK + 0
@@ -92,9 +92,9 @@ const (
PL0 = portL + 0 PL0 = portL + 0
PL1 = portL + 1 PL1 = portL + 1
PL2 = portL + 2 PL2 = portL + 2
PL3 = portL + 3 PL3 = portL + 3 // peripherals: Timer5 channel A
PL4 = portL + 4 PL4 = portL + 4 // peripherals: Timer5 channel B
PL5 = portL + 5 PL5 = portL + 5 // peripherals: Timer5 channel C
PL6 = portL + 6 PL6 = portL + 6
PL7 = portL + 7 PL7 = portL + 7
) )
+20 -25
View File
@@ -10,7 +10,6 @@ package machine
import ( import (
"device/arm" "device/arm"
"device/sam" "device/sam"
"errors"
"runtime/interrupt" "runtime/interrupt"
"unsafe" "unsafe"
) )
@@ -18,20 +17,20 @@ import (
const deviceName = sam.Device const deviceName = sam.Device
const ( const (
PinAnalog PinMode = 1
PinSERCOM PinMode = 2
PinSERCOMAlt PinMode = 3
PinTimer PinMode = 4
PinTimerAlt PinMode = 5
PinCom PinMode = 6
//PinAC_CLK PinMode = 7
PinDigital PinMode = 8
PinInput PinMode = 9 PinInput PinMode = 9
PinInputPullup PinMode = 10 PinInputPullup PinMode = 10
PinOutput PinMode = 11 PinOutput PinMode = 11
PinTCC PinMode = PinTimer
PinTCCAlt PinMode = PinTimerAlt
PinInputPulldown PinMode = 12 PinInputPulldown PinMode = 12
// internal pin modes
pinAnalog PinMode = 1
pinSERCOM PinMode = 2
pinSERCOMAlt PinMode = 3
pinTCC PinMode = 4
pinTCCAlt PinMode = 5
pinCom PinMode = 6
//PinAC_CLK PinMode = 7
pinDigital PinMode = 8
) )
type PinChange uint8 type PinChange uint8
@@ -150,7 +149,7 @@ func findPinPadMapping(sercom uint8, pin Pin) (pinMode PinMode, pad uint32, ok b
if upper != 0 { if upper != 0 {
// SERCOM // SERCOM
if (upper>>1)-1 == sercom { if (upper>>1)-1 == sercom {
pinMode = PinSERCOM pinMode = pinSERCOM
pad |= uint32((upper & 1) << 1) pad |= uint32((upper & 1) << 1)
ok = true ok = true
} }
@@ -158,7 +157,7 @@ func findPinPadMapping(sercom uint8, pin Pin) (pinMode PinMode, pad uint32, ok b
if lower != 0 { if lower != 0 {
// SERCOM-ALT // SERCOM-ALT
if (lower>>1)-1 == sercom { if (lower>>1)-1 == sercom {
pinMode = PinSERCOMAlt pinMode = pinSERCOMAlt
pad |= uint32((lower & 1) << 1) pad |= uint32((lower & 1) << 1)
ok = true ok = true
} }
@@ -382,7 +381,7 @@ func (a ADC) Configure(config ADCConfig) {
// 1/2 VDDANA = 0.5 * 3V3 = 1.65V // 1/2 VDDANA = 0.5 * 3V3 = 1.65V
sam.ADC.REFCTRL.SetBits(sam.ADC_REFCTRL_REFSEL_INTVCC1 << sam.ADC_REFCTRL_REFSEL_Pos) sam.ADC.REFCTRL.SetBits(sam.ADC_REFCTRL_REFSEL_INTVCC1 << sam.ADC_REFCTRL_REFSEL_Pos)
a.Pin.Configure(PinConfig{Mode: PinAnalog}) a.Pin.Configure(PinConfig{Mode: pinAnalog})
return return
} }
@@ -677,7 +676,7 @@ const i2cTimeout = 1000
func (i2c *I2C) Configure(config I2CConfig) error { func (i2c *I2C) Configure(config I2CConfig) error {
// Default I2C bus speed is 100 kHz. // Default I2C bus speed is 100 kHz.
if config.Frequency == 0 { if config.Frequency == 0 {
config.Frequency = TWI_FREQ_100KHZ config.Frequency = 100 * KHz
} }
if config.SDA == 0 && config.SCL == 0 { if config.SDA == 0 && config.SCL == 0 {
config.SDA = SDA_PIN config.SDA = SDA_PIN
@@ -1001,11 +1000,11 @@ func (i2s I2S) Configure(config I2SConfig) {
} }
// configure pin for clock // configure pin for clock
config.SCK.Configure(PinConfig{Mode: PinCom}) config.SCK.Configure(PinConfig{Mode: pinCom})
// configure pin for WS, if needed // configure pin for WS, if needed
if config.WS != NoPin { if config.WS != NoPin {
config.WS.Configure(PinConfig{Mode: PinCom}) config.WS.Configure(PinConfig{Mode: pinCom})
} }
// now set serializer data size. // now set serializer data size.
@@ -1044,7 +1043,7 @@ func (i2s I2S) Configure(config I2SConfig) {
} }
// configure data pin // configure data pin
config.SD.Configure(PinConfig{Mode: PinCom}) config.SD.Configure(PinConfig{Mode: pinCom})
// re-enable // re-enable
i2s.Bus.CTRLA.SetBits(sam.I2S_CTRLA_ENABLE) i2s.Bus.CTRLA.SetBits(sam.I2S_CTRLA_ENABLE)
@@ -1274,10 +1273,6 @@ func (spi SPI) Transfer(w byte) (byte, error) {
return byte(spi.Bus.DATA.Get()), nil return byte(spi.Bus.DATA.Get()), nil
} }
var (
ErrTxInvalidSliceSize = errors.New("SPI write and read slices must be same size")
)
// Tx handles read/write operation for SPI interface. Since SPI is a syncronous write/read // Tx handles read/write operation for SPI interface. Since SPI is a syncronous write/read
// interface, there must always be the same number of bytes written as bytes read. // interface, there must always be the same number of bytes written as bytes read.
// The Tx method knows about this, and offers a few different ways of calling it. // The Tx method knows about this, and offers a few different ways of calling it.
@@ -1641,12 +1636,12 @@ func findPinTimerMapping(timer uint8, pin Pin) (PinMode, uint8) {
if mapping&0x07 == timer+1 { if mapping&0x07 == timer+1 {
// PWM output is on peripheral function E. // PWM output is on peripheral function E.
evenChannel := ((mapping >> 3) & 1) * 2 evenChannel := ((mapping >> 3) & 1) * 2
return PinTCC, evenChannel + uint8(pin&1) return pinTCC, evenChannel + uint8(pin&1)
} }
if (mapping&0x70)>>4 == timer+1 { if (mapping&0x70)>>4 == timer+1 {
// PWM output is on peripheral function F. // PWM output is on peripheral function F.
evenChannel := ((mapping >> 7) & 1) * 2 evenChannel := ((mapping >> 7) & 1) * 2
return PinTCCAlt, evenChannel + uint8(pin&1) return pinTCCAlt, evenChannel + uint8(pin&1)
} }
return 0, 0 return 0, 0
} }
@@ -1740,7 +1735,7 @@ func EnterBootloader() {
// Perform magic reset into bootloader, as mentioned in // Perform magic reset into bootloader, as mentioned in
// https://github.com/arduino/ArduinoCore-samd/issues/197 // https://github.com/arduino/ArduinoCore-samd/issues/197
*(*uint32)(unsafe.Pointer(uintptr(0x20007FFC))) = RESET_MAGIC_VALUE *(*uint32)(unsafe.Pointer(uintptr(0x20007FFC))) = resetMagicValue
arm.SystemReset() arm.SystemReset()
} }
+2 -2
View File
@@ -37,8 +37,8 @@ func (dev *USBDevice) Configure(config UARTConfig) {
sam.USB_DEVICE.DESCADD.Set(uint32(uintptr(unsafe.Pointer(&usbEndpointDescriptors)))) sam.USB_DEVICE.DESCADD.Set(uint32(uintptr(unsafe.Pointer(&usbEndpointDescriptors))))
// configure pins // configure pins
USBCDC_DM_PIN.Configure(PinConfig{Mode: PinCom}) USBCDC_DM_PIN.Configure(PinConfig{Mode: pinCom})
USBCDC_DP_PIN.Configure(PinConfig{Mode: PinCom}) USBCDC_DP_PIN.Configure(PinConfig{Mode: pinCom})
// performs pad calibration from store fuses // performs pad calibration from store fuses
handlePadCalibration() handlePadCalibration()
+12 -12
View File
@@ -86,53 +86,53 @@ func (p Pin) Configure(config PinConfig) {
sam.PORT.OUTSET0.Set(1 << uint8(p)) sam.PORT.OUTSET0.Set(1 << uint8(p))
p.setPinCfg(sam.PORT_PINCFG0_INEN | sam.PORT_PINCFG0_PULLEN) p.setPinCfg(sam.PORT_PINCFG0_INEN | sam.PORT_PINCFG0_PULLEN)
case PinSERCOM: case pinSERCOM:
if uint8(p)&1 > 0 { if uint8(p)&1 > 0 {
// odd pin, so save the even pins // odd pin, so save the even pins
val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk
p.setPMux(val | (uint8(PinSERCOM) << sam.PORT_PMUX0_PMUXO_Pos)) p.setPMux(val | (uint8(pinSERCOM) << sam.PORT_PMUX0_PMUXO_Pos))
} else { } else {
// even pin, so save the odd pins // even pin, so save the odd pins
val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk
p.setPMux(val | (uint8(PinSERCOM) << sam.PORT_PMUX0_PMUXE_Pos)) p.setPMux(val | (uint8(pinSERCOM) << sam.PORT_PMUX0_PMUXE_Pos))
} }
// enable port config // enable port config
p.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR | sam.PORT_PINCFG0_INEN) p.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR | sam.PORT_PINCFG0_INEN)
case PinSERCOMAlt: case pinSERCOMAlt:
if uint8(p)&1 > 0 { if uint8(p)&1 > 0 {
// odd pin, so save the even pins // odd pin, so save the even pins
val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk
p.setPMux(val | (uint8(PinSERCOMAlt) << sam.PORT_PMUX0_PMUXO_Pos)) p.setPMux(val | (uint8(pinSERCOMAlt) << sam.PORT_PMUX0_PMUXO_Pos))
} else { } else {
// even pin, so save the odd pins // even pin, so save the odd pins
val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk
p.setPMux(val | (uint8(PinSERCOMAlt) << sam.PORT_PMUX0_PMUXE_Pos)) p.setPMux(val | (uint8(pinSERCOMAlt) << sam.PORT_PMUX0_PMUXE_Pos))
} }
// enable port config // enable port config
p.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR) p.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR)
case PinCom: case pinCom:
if uint8(p)&1 > 0 { if uint8(p)&1 > 0 {
// odd pin, so save the even pins // odd pin, so save the even pins
val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk
p.setPMux(val | (uint8(PinCom) << sam.PORT_PMUX0_PMUXO_Pos)) p.setPMux(val | (uint8(pinCom) << sam.PORT_PMUX0_PMUXO_Pos))
} else { } else {
// even pin, so save the odd pins // even pin, so save the odd pins
val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk
p.setPMux(val | (uint8(PinCom) << sam.PORT_PMUX0_PMUXE_Pos)) p.setPMux(val | (uint8(pinCom) << sam.PORT_PMUX0_PMUXE_Pos))
} }
// enable port config // enable port config
p.setPinCfg(sam.PORT_PINCFG0_PMUXEN) p.setPinCfg(sam.PORT_PINCFG0_PMUXEN)
case PinAnalog: case pinAnalog:
if uint8(p)&1 > 0 { if uint8(p)&1 > 0 {
// odd pin, so save the even pins // odd pin, so save the even pins
val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk
p.setPMux(val | (uint8(PinAnalog) << sam.PORT_PMUX0_PMUXO_Pos)) p.setPMux(val | (uint8(pinAnalog) << sam.PORT_PMUX0_PMUXO_Pos))
} else { } else {
// even pin, so save the odd pins // even pin, so save the odd pins
val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk
p.setPMux(val | (uint8(PinAnalog) << sam.PORT_PMUX0_PMUXE_Pos)) p.setPMux(val | (uint8(pinAnalog) << sam.PORT_PMUX0_PMUXE_Pos))
} }
// enable port config // enable port config
p.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR) p.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR)
+12 -12
View File
@@ -137,53 +137,53 @@ func (p Pin) Configure(config PinConfig) {
p.setPinCfg(sam.PORT_PINCFG0_INEN | sam.PORT_PINCFG0_PULLEN) p.setPinCfg(sam.PORT_PINCFG0_INEN | sam.PORT_PINCFG0_PULLEN)
} }
case PinSERCOM: case pinSERCOM:
if p&1 > 0 { if p&1 > 0 {
// odd pin, so save the even pins // odd pin, so save the even pins
val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk
p.setPMux(val | (uint8(PinSERCOM) << sam.PORT_PMUX0_PMUXO_Pos)) p.setPMux(val | (uint8(pinSERCOM) << sam.PORT_PMUX0_PMUXO_Pos))
} else { } else {
// even pin, so save the odd pins // even pin, so save the odd pins
val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk
p.setPMux(val | (uint8(PinSERCOM) << sam.PORT_PMUX0_PMUXE_Pos)) p.setPMux(val | (uint8(pinSERCOM) << sam.PORT_PMUX0_PMUXE_Pos))
} }
// enable port config // enable port config
p.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR | sam.PORT_PINCFG0_INEN) p.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR | sam.PORT_PINCFG0_INEN)
case PinSERCOMAlt: case pinSERCOMAlt:
if p&1 > 0 { if p&1 > 0 {
// odd pin, so save the even pins // odd pin, so save the even pins
val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk
p.setPMux(val | (uint8(PinSERCOMAlt) << sam.PORT_PMUX0_PMUXO_Pos)) p.setPMux(val | (uint8(pinSERCOMAlt) << sam.PORT_PMUX0_PMUXO_Pos))
} else { } else {
// even pin, so save the odd pins // even pin, so save the odd pins
val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk
p.setPMux(val | (uint8(PinSERCOMAlt) << sam.PORT_PMUX0_PMUXE_Pos)) p.setPMux(val | (uint8(pinSERCOMAlt) << sam.PORT_PMUX0_PMUXE_Pos))
} }
// enable port config // enable port config
p.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR) p.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR)
case PinCom: case pinCom:
if p&1 > 0 { if p&1 > 0 {
// odd pin, so save the even pins // odd pin, so save the even pins
val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk
p.setPMux(val | (uint8(PinCom) << sam.PORT_PMUX0_PMUXO_Pos)) p.setPMux(val | (uint8(pinCom) << sam.PORT_PMUX0_PMUXO_Pos))
} else { } else {
// even pin, so save the odd pins // even pin, so save the odd pins
val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk
p.setPMux(val | (uint8(PinCom) << sam.PORT_PMUX0_PMUXE_Pos)) p.setPMux(val | (uint8(pinCom) << sam.PORT_PMUX0_PMUXE_Pos))
} }
// enable port config // enable port config
p.setPinCfg(sam.PORT_PINCFG0_PMUXEN) p.setPinCfg(sam.PORT_PINCFG0_PMUXEN)
case PinAnalog: case pinAnalog:
if p&1 > 0 { if p&1 > 0 {
// odd pin, so save the even pins // odd pin, so save the even pins
val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk
p.setPMux(val | (uint8(PinAnalog) << sam.PORT_PMUX0_PMUXO_Pos)) p.setPMux(val | (uint8(pinAnalog) << sam.PORT_PMUX0_PMUXO_Pos))
} else { } else {
// even pin, so save the odd pins // even pin, so save the odd pins
val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk
p.setPMux(val | (uint8(PinAnalog) << sam.PORT_PMUX0_PMUXE_Pos)) p.setPMux(val | (uint8(pinAnalog) << sam.PORT_PMUX0_PMUXE_Pos))
} }
// enable port config // enable port config
p.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR) p.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR)
+106 -112
View File
@@ -10,7 +10,6 @@ package machine
import ( import (
"device/arm" "device/arm"
"device/sam" "device/sam"
"errors"
"runtime/interrupt" "runtime/interrupt"
"unsafe" "unsafe"
) )
@@ -22,30 +21,29 @@ func CPUFrequency() uint32 {
} }
const ( const (
PinAnalog PinMode = 1
PinSERCOM PinMode = 2
PinSERCOMAlt PinMode = 3
PinTimer PinMode = 4
PinTimerAlt PinMode = 5
PinTCCPDEC PinMode = 6
PinCom PinMode = 7
PinSDHC PinMode = 8
PinI2S PinMode = 9
PinPCC PinMode = 10
PinGMAC PinMode = 11
PinACCLK PinMode = 12
PinCCL PinMode = 13
PinDigital PinMode = 14
PinInput PinMode = 15 PinInput PinMode = 15
PinInputPullup PinMode = 16 PinInputPullup PinMode = 16
PinOutput PinMode = 17 PinOutput PinMode = 17
PinTCCE PinMode = PinTimer
PinTCCF PinMode = PinTimerAlt
PinTCCG PinMode = PinTCCPDEC
PinInputPulldown PinMode = 18 PinInputPulldown PinMode = 18
PinCAN PinMode = 19
PinCAN0 PinMode = PinSDHC // internal pin modes
PinCAN1 PinMode = PinCom pinAnalog PinMode = 1
pinSERCOM PinMode = 2
pinSERCOMAlt PinMode = 3
pinTCCE PinMode = 4
pinTCCF PinMode = 5
pinTCCG PinMode = 6
pinCom PinMode = 7
pinSDHC PinMode = 8
pinI2S PinMode = 9
pinPCC PinMode = 10
pinGMAC PinMode = 11
pinACCLK PinMode = 12
pinCCL PinMode = 13
pinDigital PinMode = 14
pinCAN PinMode = 19
pinCAN0 PinMode = pinSDHC
pinCAN1 PinMode = pinCom
) )
type PinChange uint8 type PinChange uint8
@@ -78,86 +76,86 @@ const (
PA05 Pin = 5 PA05 Pin = 5
PA06 Pin = 6 PA06 Pin = 6
PA07 Pin = 7 PA07 Pin = 7
PA08 Pin = 8 PA08 Pin = 8 // peripherals: TCC0 channel 0, TCC1 channel 4
PA09 Pin = 9 PA09 Pin = 9 // peripherals: TCC0 channel 1, TCC1 channel 5
PA10 Pin = 10 PA10 Pin = 10 // peripherals: TCC0 channel 2, TCC1 channel 6
PA11 Pin = 11 PA11 Pin = 11 // peripherals: TCC0 channel 3, TCC1 channel 7
PA12 Pin = 12 PA12 Pin = 12 // peripherals: TCC0 channel 6, TCC1 channel 2
PA13 Pin = 13 PA13 Pin = 13 // peripherals: TCC0 channel 7, TCC1 channel 3
PA14 Pin = 14 PA14 Pin = 14 // peripherals: TCC2 channel 0, TCC1 channel 2
PA15 Pin = 15 PA15 Pin = 15 // peripherals: TCC2 channel 1, TCC1 channel 3
PA16 Pin = 16 PA16 Pin = 16 // peripherals: TCC1 channel 0, TCC0 channel 4
PA17 Pin = 17 PA17 Pin = 17 // peripherals: TCC1 channel 1, TCC0 channel 5
PA18 Pin = 18 PA18 Pin = 18 // peripherals: TCC1 channel 2, TCC0 channel 6
PA19 Pin = 19 PA19 Pin = 19 // peripherals: TCC1 channel 3, TCC0 channel 7
PA20 Pin = 20 PA20 Pin = 20 // peripherals: TCC1 channel 4, TCC0 channel 0
PA21 Pin = 21 PA21 Pin = 21 // peripherals: TCC1 channel 5, TCC0 channel 1
PA22 Pin = 22 PA22 Pin = 22 // peripherals: TCC1 channel 6, TCC0 channel 2
PA23 Pin = 23 PA23 Pin = 23 // peripherals: TCC1 channel 7, TCC0 channel 3
PA24 Pin = 24 PA24 Pin = 24 // peripherals: TCC2 channel 2
PA25 Pin = 25 PA25 Pin = 25 // peripherals: TCC2 channel 3
PA26 Pin = 26 PA26 Pin = 26
PA27 Pin = 27 PA27 Pin = 27
PA28 Pin = 28 PA28 Pin = 28
PA29 Pin = 29 PA29 Pin = 29
PA30 Pin = 30 PA30 Pin = 30 // peripherals: TCC2 channel 0
PA31 Pin = 31 PA31 Pin = 31 // peripherals: TCC2 channel 1
PB00 Pin = 32 PB00 Pin = 32
PB01 Pin = 33 PB01 Pin = 33
PB02 Pin = 34 PB02 Pin = 34 // peripherals: TCC2 channel 2
PB03 Pin = 35 PB03 Pin = 35 // peripherals: TCC2 channel 3
PB04 Pin = 36 PB04 Pin = 36
PB05 Pin = 37 PB05 Pin = 37
PB06 Pin = 38 PB06 Pin = 38
PB07 Pin = 39 PB07 Pin = 39
PB08 Pin = 40 PB08 Pin = 40
PB09 Pin = 41 PB09 Pin = 41
PB10 Pin = 42 PB10 Pin = 42 // peripherals: TCC0 channel 4, TCC1 channel 0
PB11 Pin = 43 PB11 Pin = 43 // peripherals: TCC0 channel 5, TCC1 channel 1
PB12 Pin = 44 PB12 Pin = 44 // peripherals: TCC3 channel 0, TCC0 channel 0
PB13 Pin = 45 PB13 Pin = 45 // peripherals: TCC3 channel 1, TCC0 channel 1
PB14 Pin = 46 PB14 Pin = 46 // peripherals: TCC4 channel 0, TCC0 channel 2
PB15 Pin = 47 PB15 Pin = 47 // peripherals: TCC4 channel 1, TCC0 channel 3
PB16 Pin = 48 PB16 Pin = 48 // peripherals: TCC3 channel 0, TCC0 channel 4
PB17 Pin = 49 PB17 Pin = 49 // peripherals: TCC3 channel 1, TCC0 channel 5
PB18 Pin = 50 PB18 Pin = 50 // peripherals: TCC1 channel 0
PB19 Pin = 51 PB19 Pin = 51 // peripherals: TCC1 channel 1
PB20 Pin = 52 PB20 Pin = 52 // peripherals: TCC1 channel 2
PB21 Pin = 53 PB21 Pin = 53 // peripherals: TCC1 channel 3
PB22 Pin = 54 PB22 Pin = 54
PB23 Pin = 55 PB23 Pin = 55
PB24 Pin = 56 PB24 Pin = 56
PB25 Pin = 57 PB25 Pin = 57
PB26 Pin = 58 PB26 Pin = 58 // peripherals: TCC1 channel 2
PB27 Pin = 59 PB27 Pin = 59 // peripherals: TCC1 channel 3
PB28 Pin = 60 PB28 Pin = 60 // peripherals: TCC1 channel 4
PB29 Pin = 61 PB29 Pin = 61 // peripherals: TCC1 channel 5
PB30 Pin = 62 PB30 Pin = 62 // peripherals: TCC4 channel 0, TCC0 channel 6
PB31 Pin = 63 PB31 Pin = 63 // peripherals: TCC4 channel 1, TCC0 channel 7
PC00 Pin = 64 PC00 Pin = 64
PC01 Pin = 65 PC01 Pin = 65
PC02 Pin = 66 PC02 Pin = 66
PC03 Pin = 67 PC03 Pin = 67
PC04 Pin = 68 PC04 Pin = 68 // peripherals: TCC0 channel 0
PC05 Pin = 69 PC05 Pin = 69 // peripherals: TCC0 channel 1
PC06 Pin = 70 PC06 Pin = 70
PC07 Pin = 71 PC07 Pin = 71
PC08 Pin = 72 PC08 Pin = 72
PC09 Pin = 73 PC09 Pin = 73
PC10 Pin = 74 PC10 Pin = 74 // peripherals: TCC0 channel 0, TCC1 channel 4
PC11 Pin = 75 PC11 Pin = 75 // peripherals: TCC0 channel 1, TCC1 channel 5
PC12 Pin = 76 PC12 Pin = 76 // peripherals: TCC0 channel 2, TCC1 channel 6
PC13 Pin = 77 PC13 Pin = 77 // peripherals: TCC0 channel 3, TCC1 channel 7
PC14 Pin = 78 PC14 Pin = 78 // peripherals: TCC0 channel 4, TCC1 channel 0
PC15 Pin = 79 PC15 Pin = 79 // peripherals: TCC0 channel 5, TCC1 channel 1
PC16 Pin = 80 PC16 Pin = 80 // peripherals: TCC0 channel 0
PC17 Pin = 81 PC17 Pin = 81 // peripherals: TCC0 channel 1
PC18 Pin = 82 PC18 Pin = 82 // peripherals: TCC0 channel 2
PC19 Pin = 83 PC19 Pin = 83 // peripherals: TCC0 channel 3
PC20 Pin = 84 PC20 Pin = 84 // peripherals: TCC0 channel 4
PC21 Pin = 85 PC21 Pin = 85 // peripherals: TCC0 channel 5
PC22 Pin = 86 PC22 Pin = 86 // peripherals: TCC0 channel 6
PC23 Pin = 87 PC23 Pin = 87 // peripherals: TCC0 channel 7
PC24 Pin = 88 PC24 Pin = 88
PC25 Pin = 89 PC25 Pin = 89
PC26 Pin = 90 PC26 Pin = 90
@@ -174,20 +172,20 @@ const (
PD05 Pin = 101 PD05 Pin = 101
PD06 Pin = 102 PD06 Pin = 102
PD07 Pin = 103 PD07 Pin = 103
PD08 Pin = 104 PD08 Pin = 104 // peripherals: TCC0 channel 1
PD09 Pin = 105 PD09 Pin = 105 // peripherals: TCC0 channel 2
PD10 Pin = 106 PD10 Pin = 106 // peripherals: TCC0 channel 3
PD11 Pin = 107 PD11 Pin = 107 // peripherals: TCC0 channel 4
PD12 Pin = 108 PD12 Pin = 108 // peripherals: TCC0 channel 5
PD13 Pin = 109 PD13 Pin = 109 // peripherals: TCC0 channel 6
PD14 Pin = 110 PD14 Pin = 110
PD15 Pin = 111 PD15 Pin = 111
PD16 Pin = 112 PD16 Pin = 112
PD17 Pin = 113 PD17 Pin = 113
PD18 Pin = 114 PD18 Pin = 114
PD19 Pin = 115 PD19 Pin = 115
PD20 Pin = 116 PD20 Pin = 116 // peripherals: TCC1 channel 0
PD21 Pin = 117 PD21 Pin = 117 // peripherals: TCC1 channel 1
PD22 Pin = 118 PD22 Pin = 118
PD23 Pin = 119 PD23 Pin = 119
PD24 Pin = 120 PD24 Pin = 120
@@ -339,7 +337,7 @@ func findPinPadMapping(sercom uint8, pin Pin) (pinMode PinMode, pad uint32, ok b
if upper != 0 { if upper != 0 {
// SERCOM // SERCOM
if (upper>>4)-1 == sercom { if (upper>>4)-1 == sercom {
pinMode = PinSERCOM pinMode = pinSERCOM
pad |= uint32(upper % 4) pad |= uint32(upper % 4)
ok = true ok = true
} }
@@ -347,7 +345,7 @@ func findPinPadMapping(sercom uint8, pin Pin) (pinMode PinMode, pad uint32, ok b
if lower != 0 { if lower != 0 {
// SERCOM-ALT // SERCOM-ALT
if (lower>>4)-1 == sercom { if (lower>>4)-1 == sercom {
pinMode = PinSERCOMAlt pinMode = pinSERCOMAlt
pad |= uint32(lower % 4) pad |= uint32(lower % 4)
ok = true ok = true
} }
@@ -581,65 +579,65 @@ func (p Pin) Configure(config PinConfig) {
sam.PORT.GROUP[group].OUTSET.Set(1 << pin_in_group) sam.PORT.GROUP[group].OUTSET.Set(1 << pin_in_group)
p.setPinCfg(sam.PORT_GROUP_PINCFG_INEN | sam.PORT_GROUP_PINCFG_PULLEN) p.setPinCfg(sam.PORT_GROUP_PINCFG_INEN | sam.PORT_GROUP_PINCFG_PULLEN)
case PinSERCOM: case pinSERCOM:
if p&1 > 0 { if p&1 > 0 {
// odd pin, so save the even pins // odd pin, so save the even pins
val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXE_Msk val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXE_Msk
p.setPMux(val | (uint8(PinSERCOM) << sam.PORT_GROUP_PMUX_PMUXO_Pos)) p.setPMux(val | (uint8(pinSERCOM) << sam.PORT_GROUP_PMUX_PMUXO_Pos))
} else { } else {
// even pin, so save the odd pins // even pin, so save the odd pins
val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXO_Msk val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXO_Msk
p.setPMux(val | (uint8(PinSERCOM) << sam.PORT_GROUP_PMUX_PMUXE_Pos)) p.setPMux(val | (uint8(pinSERCOM) << sam.PORT_GROUP_PMUX_PMUXE_Pos))
} }
// enable port config // enable port config
p.setPinCfg(sam.PORT_GROUP_PINCFG_PMUXEN | sam.PORT_GROUP_PINCFG_DRVSTR | sam.PORT_GROUP_PINCFG_INEN) p.setPinCfg(sam.PORT_GROUP_PINCFG_PMUXEN | sam.PORT_GROUP_PINCFG_DRVSTR | sam.PORT_GROUP_PINCFG_INEN)
case PinSERCOMAlt: case pinSERCOMAlt:
if p&1 > 0 { if p&1 > 0 {
// odd pin, so save the even pins // odd pin, so save the even pins
val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXE_Msk val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXE_Msk
p.setPMux(val | (uint8(PinSERCOMAlt) << sam.PORT_GROUP_PMUX_PMUXO_Pos)) p.setPMux(val | (uint8(pinSERCOMAlt) << sam.PORT_GROUP_PMUX_PMUXO_Pos))
} else { } else {
// even pin, so save the odd pins // even pin, so save the odd pins
val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXO_Msk val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXO_Msk
p.setPMux(val | (uint8(PinSERCOMAlt) << sam.PORT_GROUP_PMUX_PMUXE_Pos)) p.setPMux(val | (uint8(pinSERCOMAlt) << sam.PORT_GROUP_PMUX_PMUXE_Pos))
} }
// enable port config // enable port config
p.setPinCfg(sam.PORT_GROUP_PINCFG_PMUXEN | sam.PORT_GROUP_PINCFG_DRVSTR) p.setPinCfg(sam.PORT_GROUP_PINCFG_PMUXEN | sam.PORT_GROUP_PINCFG_DRVSTR)
case PinCom: case pinCom:
if p&1 > 0 { if p&1 > 0 {
// odd pin, so save the even pins // odd pin, so save the even pins
val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXE_Msk val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXE_Msk
p.setPMux(val | (uint8(PinCom) << sam.PORT_GROUP_PMUX_PMUXO_Pos)) p.setPMux(val | (uint8(pinCom) << sam.PORT_GROUP_PMUX_PMUXO_Pos))
} else { } else {
// even pin, so save the odd pins // even pin, so save the odd pins
val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXO_Msk val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXO_Msk
p.setPMux(val | (uint8(PinCom) << sam.PORT_GROUP_PMUX_PMUXE_Pos)) p.setPMux(val | (uint8(pinCom) << sam.PORT_GROUP_PMUX_PMUXE_Pos))
} }
// enable port config // enable port config
p.setPinCfg(sam.PORT_GROUP_PINCFG_PMUXEN) p.setPinCfg(sam.PORT_GROUP_PINCFG_PMUXEN)
case PinAnalog: case pinAnalog:
if p&1 > 0 { if p&1 > 0 {
// odd pin, so save the even pins // odd pin, so save the even pins
val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXE_Msk val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXE_Msk
p.setPMux(val | (uint8(PinAnalog) << sam.PORT_GROUP_PMUX_PMUXO_Pos)) p.setPMux(val | (uint8(pinAnalog) << sam.PORT_GROUP_PMUX_PMUXO_Pos))
} else { } else {
// even pin, so save the odd pins // even pin, so save the odd pins
val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXO_Msk val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXO_Msk
p.setPMux(val | (uint8(PinAnalog) << sam.PORT_GROUP_PMUX_PMUXE_Pos)) p.setPMux(val | (uint8(pinAnalog) << sam.PORT_GROUP_PMUX_PMUXE_Pos))
} }
// enable port config // enable port config
p.setPinCfg(sam.PORT_GROUP_PINCFG_PMUXEN | sam.PORT_GROUP_PINCFG_DRVSTR) p.setPinCfg(sam.PORT_GROUP_PINCFG_PMUXEN | sam.PORT_GROUP_PINCFG_DRVSTR)
case PinSDHC: case pinSDHC:
if p&1 > 0 { if p&1 > 0 {
// odd pin, so save the even pins // odd pin, so save the even pins
val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXE_Msk val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXE_Msk
p.setPMux(val | (uint8(PinSDHC) << sam.PORT_GROUP_PMUX_PMUXO_Pos)) p.setPMux(val | (uint8(pinSDHC) << sam.PORT_GROUP_PMUX_PMUXO_Pos))
} else { } else {
// even pin, so save the odd pins // even pin, so save the odd pins
val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXO_Msk val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXO_Msk
p.setPMux(val | (uint8(PinSDHC) << sam.PORT_GROUP_PMUX_PMUXE_Pos)) p.setPMux(val | (uint8(pinSDHC) << sam.PORT_GROUP_PMUX_PMUXE_Pos))
} }
// enable port config // enable port config
p.setPinCfg(sam.PORT_GROUP_PINCFG_PMUXEN) p.setPinCfg(sam.PORT_GROUP_PINCFG_PMUXEN)
@@ -815,7 +813,7 @@ func (a ADC) Configure(config ADCConfig) {
adc.REFCTRL.SetBits(sam.ADC_REFCTRL_REFSEL_INTVCC1) adc.REFCTRL.SetBits(sam.ADC_REFCTRL_REFSEL_INTVCC1)
} }
a.Pin.Configure(PinConfig{Mode: PinAnalog}) a.Pin.Configure(PinConfig{Mode: pinAnalog})
} }
// Get returns the current value of a ADC pin, in the range 0..0xffff. // Get returns the current value of a ADC pin, in the range 0..0xffff.
@@ -1151,7 +1149,7 @@ const i2cTimeout = 1000
func (i2c *I2C) Configure(config I2CConfig) error { func (i2c *I2C) Configure(config I2CConfig) error {
// Default I2C bus speed is 100 kHz. // Default I2C bus speed is 100 kHz.
if config.Frequency == 0 { if config.Frequency == 0 {
config.Frequency = TWI_FREQ_100KHZ config.Frequency = 100 * KHz
} }
// Use default I2C pins if not set. // Use default I2C pins if not set.
@@ -1527,10 +1525,6 @@ func (spi SPI) Transfer(w byte) (byte, error) {
return byte(spi.Bus.DATA.Get()), nil return byte(spi.Bus.DATA.Get()), nil
} }
var (
ErrTxInvalidSliceSize = errors.New("SPI write and read slices must be same size")
)
// Tx handles read/write operation for SPI interface. Since SPI is a syncronous write/read // Tx handles read/write operation for SPI interface. Since SPI is a syncronous write/read
// interface, there must always be the same number of bytes written as bytes read. // interface, there must always be the same number of bytes written as bytes read.
// The Tx method knows about this, and offers a few different ways of calling it. // The Tx method knows about this, and offers a few different ways of calling it.
@@ -1872,7 +1866,7 @@ var pinTimerMapping = [...]struct{ F, G uint8 }{
PB02 / 2: {pinTCC2_2, 0}, PB02 / 2: {pinTCC2_2, 0},
} }
// findPinPadMapping returns the pin mode (PinTCCF or PinTCCG) and the channel // findPinPadMapping returns the pin mode (pinTCCF or pinTCCG) and the channel
// number for a given timer and pin. A zero PinMode is returned if no mapping // number for a given timer and pin. A zero PinMode is returned if no mapping
// could be found. // could be found.
func findPinTimerMapping(timer uint8, pin Pin) (PinMode, uint8) { func findPinTimerMapping(timer uint8, pin Pin) (PinMode, uint8) {
@@ -1884,12 +1878,12 @@ func findPinTimerMapping(timer uint8, pin Pin) (PinMode, uint8) {
// Check for column F in the datasheet. // Check for column F in the datasheet.
if mapping.F>>4-1 == timer { if mapping.F>>4-1 == timer {
return PinTCCF, mapping.F&0x0f + uint8(pin)&1 return pinTCCF, mapping.F&0x0f + uint8(pin)&1
} }
// Check for column G in the datasheet. // Check for column G in the datasheet.
if mapping.G>>4-1 == timer { if mapping.G>>4-1 == timer {
return PinTCCG, mapping.G&0x0f + uint8(pin)&1 return pinTCCG, mapping.G&0x0f + uint8(pin)&1
} }
// Nothing found. // Nothing found.
@@ -1980,7 +1974,7 @@ func EnterBootloader() {
// Perform magic reset into bootloader, as mentioned in // Perform magic reset into bootloader, as mentioned in
// https://github.com/arduino/ArduinoCore-samd/issues/197 // https://github.com/arduino/ArduinoCore-samd/issues/197
*(*uint32)(unsafe.Pointer(uintptr(0x20000000 + HSRAM_SIZE - 4))) = RESET_MAGIC_VALUE *(*uint32)(unsafe.Pointer(uintptr(0x20000000 + HSRAM_SIZE - 4))) = resetMagicValue
arm.SystemReset() arm.SystemReset()
} }
+2 -2
View File
@@ -37,8 +37,8 @@ func (dev *USBDevice) Configure(config UARTConfig) {
sam.USB_DEVICE.DESCADD.Set(uint32(uintptr(unsafe.Pointer(&usbEndpointDescriptors)))) sam.USB_DEVICE.DESCADD.Set(uint32(uintptr(unsafe.Pointer(&usbEndpointDescriptors))))
// configure pins // configure pins
USBCDC_DM_PIN.Configure(PinConfig{Mode: PinCom}) USBCDC_DM_PIN.Configure(PinConfig{Mode: pinCom})
USBCDC_DP_PIN.Configure(PinConfig{Mode: PinCom}) USBCDC_DP_PIN.Configure(PinConfig{Mode: pinCom})
// performs pad calibration from store fuses // performs pad calibration from store fuses
handlePadCalibration() handlePadCalibration()
+2 -2
View File
@@ -68,9 +68,9 @@ func (can *CAN) Configure(config CANConfig) error {
config.Standby.Low() config.Standby.Low()
} }
mode := PinCAN0 mode := pinCAN0
if can.instance() == 1 { if can.instance() == 1 {
mode = PinCAN1 mode = pinCAN1
} }
config.Rx.Configure(PinConfig{Mode: mode}) config.Rx.Configure(PinConfig{Mode: mode})
+2 -14
View File
@@ -59,12 +59,9 @@ type PinChange uint8
// Pin change interrupt constants for SetInterrupt. // Pin change interrupt constants for SetInterrupt.
const ( const (
PinNoInterrupt PinChange = iota PinRising PinChange = iota + 1
PinRising
PinFalling PinFalling
PinToggle PinToggle
PinLowLevel
PinHighLevel
) )
// Configure this pin with the given configuration. // Configure this pin with the given configuration.
@@ -190,7 +187,7 @@ func (p Pin) SetInterrupt(change PinChange, callback func(Pin)) (err error) {
return ErrInvalidInputPin return ErrInvalidInputPin
} }
if callback == nil || change == PinNoInterrupt { if callback == nil {
// Disable this pin interrupt // Disable this pin interrupt
p.pin().ClearBits(esp.GPIO_PIN_PIN_INT_TYPE_Msk | esp.GPIO_PIN_PIN_INT_ENA_Msk) p.pin().ClearBits(esp.GPIO_PIN_PIN_INT_TYPE_Msk | esp.GPIO_PIN_PIN_INT_ENA_Msk)
@@ -264,15 +261,6 @@ type UART struct {
DataOverflowDetected bool // set when data overflow detected in UART FIFO buffer or RingBuffer DataOverflowDetected bool // set when data overflow detected in UART FIFO buffer or RingBuffer
} }
type UARTStopBits int
const (
UARTStopBits_Default UARTStopBits = iota
UARTStopBits_1
UARTStopBits_1_5
UARTStopBits_2
)
const ( const (
defaultDataBits = 8 defaultDataBits = 8
defaultStopBit = 1 defaultStopBit = 1
+13 -11
View File
@@ -18,9 +18,11 @@ func CPUFrequency() uint32 {
const ( const (
PinInput PinMode = iota PinInput PinMode = iota
PinOutput PinOutput
PinPWM
PinSPI // internal pin modes
PinI2C = PinSPI pinPWM
pinSPI
pinI2C = pinSPI
) )
// Configure this pin with the given configuration. // Configure this pin with the given configuration.
@@ -29,10 +31,10 @@ func (p Pin) Configure(config PinConfig) {
switch config.Mode { switch config.Mode {
case PinOutput: case PinOutput:
sifive.GPIO0.OUTPUT_EN.SetBits(1 << uint8(p)) sifive.GPIO0.OUTPUT_EN.SetBits(1 << uint8(p))
case PinPWM: case pinPWM:
sifive.GPIO0.IOF_EN.SetBits(1 << uint8(p)) sifive.GPIO0.IOF_EN.SetBits(1 << uint8(p))
sifive.GPIO0.IOF_SEL.SetBits(1 << uint8(p)) sifive.GPIO0.IOF_SEL.SetBits(1 << uint8(p))
case PinSPI: case pinSPI:
sifive.GPIO0.IOF_EN.SetBits(1 << uint8(p)) sifive.GPIO0.IOF_EN.SetBits(1 << uint8(p))
sifive.GPIO0.IOF_SEL.ClearBits(1 << uint8(p)) sifive.GPIO0.IOF_SEL.ClearBits(1 << uint8(p))
} }
@@ -145,9 +147,9 @@ func (spi SPI) Configure(config SPIConfig) error {
} }
// enable pins for SPI // enable pins for SPI
config.SCK.Configure(PinConfig{Mode: PinSPI}) config.SCK.Configure(PinConfig{Mode: pinSPI})
config.SDO.Configure(PinConfig{Mode: PinSPI}) config.SDO.Configure(PinConfig{Mode: pinSPI})
config.SDI.Configure(PinConfig{Mode: PinSPI}) config.SDI.Configure(PinConfig{Mode: pinSPI})
// set default frequency // set default frequency
if config.Frequency == 0 { if config.Frequency == 0 {
@@ -231,7 +233,7 @@ type I2CConfig struct {
func (i2c *I2C) Configure(config I2CConfig) error { func (i2c *I2C) Configure(config I2CConfig) error {
var i2cClockFrequency uint32 = 32000000 var i2cClockFrequency uint32 = 32000000
if config.Frequency == 0 { if config.Frequency == 0 {
config.Frequency = TWI_FREQ_100KHZ config.Frequency = 100 * KHz
} }
if config.SDA == 0 && config.SCL == 0 { if config.SDA == 0 && config.SCL == 0 {
@@ -251,8 +253,8 @@ func (i2c *I2C) Configure(config I2CConfig) error {
// enable controller // enable controller
i2c.Bus.CTR.SetBits(sifive.I2C_CTR_EN) i2c.Bus.CTR.SetBits(sifive.I2C_CTR_EN)
config.SDA.Configure(PinConfig{Mode: PinI2C}) config.SDA.Configure(PinConfig{Mode: pinI2C})
config.SCL.Configure(PinConfig{Mode: PinI2C}) config.SCL.Configure(PinConfig{Mode: pinI2C})
return nil return nil
} }
+11 -5
View File
@@ -23,11 +23,17 @@ type PinChange uint8
// Pin modes. // Pin modes.
const ( const (
PinInput PinMode = iota PinInput PinMode = iota
PinInputPullUp PinInputPullup
PinInputPullDown PinInputPulldown
PinOutput PinOutput
) )
// Deprecated: use PinInputPullup and PinInputPulldown instead.
const (
PinInputPullUp = PinInputPullup
PinInputPullDown = PinInputPulldown
)
// FPIOA internal pull resistors. // FPIOA internal pull resistors.
const ( const (
fpioaPullNone fpioaPullMode = iota fpioaPullNone fpioaPullMode = iota
@@ -89,10 +95,10 @@ func (p Pin) Configure(config PinConfig) {
case PinInput: case PinInput:
p.setFPIOAIOPull(fpioaPullNone) p.setFPIOAIOPull(fpioaPullNone)
input = true input = true
case PinInputPullUp: case PinInputPullup:
p.setFPIOAIOPull(fpioaPullUp) p.setFPIOAIOPull(fpioaPullUp)
input = true input = true
case PinInputPullDown: case PinInputPulldown:
p.setFPIOAIOPull(fpioaPullDown) p.setFPIOAIOPull(fpioaPullDown)
input = true input = true
case PinOutput: case PinOutput:
@@ -517,7 +523,7 @@ type I2CConfig struct {
func (i2c *I2C) Configure(config I2CConfig) error { func (i2c *I2C) Configure(config I2CConfig) error {
if config.Frequency == 0 { if config.Frequency == 0 {
config.Frequency = TWI_FREQ_100KHZ config.Frequency = 100 * KHz
} }
if config.SDA == 0 && config.SCL == 0 { if config.SDA == 0 && config.SCL == 0 {
+39 -35
View File
@@ -21,36 +21,40 @@ func CPUFrequency() uint32 {
const ( const (
// GPIO // GPIO
PinInput PinMode = iota PinInput PinMode = iota
PinInputPullUp PinInputPullup
PinInputPullDown PinInputPulldown
PinOutput PinOutput
PinOutputOpenDrain PinOutputOpenDrain
PinDisable PinDisable
// ADC // ADC
PinInputAnalog pinInputAnalog
// UART // UART
PinModeUARTTX pinModeUARTTX
PinModeUARTRX pinModeUARTRX
// SPI // SPI
PinModeSPISDI pinModeSPISDI
PinModeSPISDO pinModeSPISDO
PinModeSPICLK pinModeSPICLK
PinModeSPICS pinModeSPICS
// I2C // I2C
PinModeI2CSDA pinModeI2CSDA
PinModeI2CSCL pinModeI2CSCL
)
// Deprecated: use PinInputPullup and PinInputPulldown instead.
const (
PinInputPullUp = PinInputPullup
PinInputPullDown = PinInputPulldown
) )
type PinChange uint8 type PinChange uint8
const ( const (
PinLow PinChange = iota PinRising PinChange = iota + 2
PinHigh
PinRising
PinFalling PinFalling
PinToggle PinToggle
) )
@@ -259,11 +263,11 @@ func (p Pin) Configure(config PinConfig) {
gpio.GDIR.ClearBits(p.getMask()) gpio.GDIR.ClearBits(p.getMask())
pad.Set(dse(7)) pad.Set(dse(7))
case PinInputPullUp: case PinInputPullup:
gpio.GDIR.ClearBits(p.getMask()) gpio.GDIR.ClearBits(p.getMask())
pad.Set(dse(7) | pke | pue | pup(3) | hys) pad.Set(dse(7) | pke | pue | pup(3) | hys)
case PinInputPullDown: case PinInputPulldown:
gpio.GDIR.ClearBits(p.getMask()) gpio.GDIR.ClearBits(p.getMask())
pad.Set(dse(7) | pke | pue | hys) pad.Set(dse(7) | pke | pue | hys)
@@ -279,29 +283,29 @@ func (p Pin) Configure(config PinConfig) {
gpio.GDIR.ClearBits(p.getMask()) gpio.GDIR.ClearBits(p.getMask())
pad.Set(dse(7) | hys) pad.Set(dse(7) | hys)
case PinInputAnalog: case pinInputAnalog:
gpio.GDIR.ClearBits(p.getMask()) gpio.GDIR.ClearBits(p.getMask())
pad.Set(dse(7)) pad.Set(dse(7))
case PinModeUARTTX: case pinModeUARTTX:
pad.Set(sre | dse(3) | spd(3)) pad.Set(sre | dse(3) | spd(3))
case PinModeUARTRX: case pinModeUARTRX:
pad.Set(dse(7) | pke | pue | pup(3) | hys) pad.Set(dse(7) | pke | pue | pup(3) | hys)
case PinModeSPISDI: case pinModeSPISDI:
pad.Set(dse(7) | spd(2)) pad.Set(dse(7) | spd(2))
case PinModeSPISDO: case pinModeSPISDO:
pad.Set(dse(7) | spd(2)) pad.Set(dse(7) | spd(2))
case PinModeSPICLK: case pinModeSPICLK:
pad.Set(dse(7) | spd(2)) pad.Set(dse(7) | spd(2))
case PinModeSPICS: case pinModeSPICS:
pad.Set(dse(7)) pad.Set(dse(7))
case PinModeI2CSDA, PinModeI2CSCL: case pinModeI2CSDA, pinModeI2CSCL:
pad.Set(ode | sre | dse(4) | spd(1) | pke | pue | pup(3)) pad.Set(ode | sre | dse(4) | spd(1) | pke | pue | pup(3))
} }
@@ -387,7 +391,7 @@ func (p Pin) SetInterrupt(change PinChange, callback func(Pin)) error {
mask := p.getMask() mask := p.getMask()
if nil != callback { if nil != callback {
switch change { switch change {
case PinLow, PinHigh, PinRising, PinFalling: case PinRising, PinFalling:
gpio.EDGE_SEL.ClearBits(mask) gpio.EDGE_SEL.ClearBits(mask)
var reg *volatile.Register32 var reg *volatile.Register32
var pos uint8 var pos uint8
@@ -746,7 +750,7 @@ func (p Pin) getMuxMode(config PinConfig) uint32 {
switch config.Mode { switch config.Mode {
// GPIO // GPIO
case PinInput, PinInputPullUp, PinInputPullDown, case PinInput, PinInputPullup, PinInputPulldown,
PinOutput, PinOutputOpenDrain, PinDisable: PinOutput, PinOutputOpenDrain, PinDisable:
mode := uint32(0x5) // GPIO is always alternate function 5 mode := uint32(0x5) // GPIO is always alternate function 5
if forcePath { if forcePath {
@@ -755,7 +759,7 @@ func (p Pin) getMuxMode(config PinConfig) uint32 {
return mode return mode
// ADC // ADC
case PinInputAnalog: case pinInputAnalog:
mode := uint32(0x5) // use alternate function 5 (GPIO) mode := uint32(0x5) // use alternate function 5 (GPIO)
if forcePath { if forcePath {
mode |= 0x10 // SION bit mode |= 0x10 // SION bit
@@ -763,7 +767,7 @@ func (p Pin) getMuxMode(config PinConfig) uint32 {
return mode return mode
// UART RX/TX // UART RX/TX
case PinModeUARTRX, PinModeUARTTX: case pinModeUARTRX, pinModeUARTTX:
mode := uint32(0x2) // UART is usually alternate function 2 on Teensy 4.x mode := uint32(0x2) // UART is usually alternate function 2 on Teensy 4.x
// Teensy 4.1 has a UART (LPUART5) with alternate function 1 // Teensy 4.1 has a UART (LPUART5) with alternate function 1
if p == PB28 || p == PB29 { if p == PB28 || p == PB29 {
@@ -772,7 +776,7 @@ func (p Pin) getMuxMode(config PinConfig) uint32 {
return mode return mode
// SPI SDI // SPI SDI
case PinModeSPISDI: case pinModeSPISDI:
var mode uint32 var mode uint32
switch p { switch p {
case PC15: // LPSPI1 SDI on PC15 alternate function 4 case PC15: // LPSPI1 SDI on PC15 alternate function 4
@@ -790,7 +794,7 @@ func (p Pin) getMuxMode(config PinConfig) uint32 {
return mode return mode
// SPI SDO // SPI SDO
case PinModeSPISDO: case pinModeSPISDO:
var mode uint32 var mode uint32
switch p { switch p {
case PC14: // LPSPI1 SDO on PC14 alternate function 4 case PC14: // LPSPI1 SDO on PC14 alternate function 4
@@ -808,7 +812,7 @@ func (p Pin) getMuxMode(config PinConfig) uint32 {
return mode return mode
// SPI SCK // SPI SCK
case PinModeSPICLK: case pinModeSPICLK:
var mode uint32 var mode uint32
switch p { switch p {
case PC12: // LPSPI1 SCK on PC12 alternate function 4 case PC12: // LPSPI1 SCK on PC12 alternate function 4
@@ -826,7 +830,7 @@ func (p Pin) getMuxMode(config PinConfig) uint32 {
return mode return mode
// SPI CS // SPI CS
case PinModeSPICS: case pinModeSPICS:
var mode uint32 var mode uint32
switch p { switch p {
case PC13: // LPSPI1 CS on PC13 alternate function 4 case PC13: // LPSPI1 CS on PC13 alternate function 4
@@ -844,7 +848,7 @@ func (p Pin) getMuxMode(config PinConfig) uint32 {
return mode return mode
// I2C SDA // I2C SDA
case PinModeI2CSDA: case pinModeI2CSDA:
var mode uint32 var mode uint32
switch p { switch p {
case PA13: // LPI2C4 SDA on PA13 alternate function 0 case PA13: // LPI2C4 SDA on PA13 alternate function 0
@@ -862,7 +866,7 @@ func (p Pin) getMuxMode(config PinConfig) uint32 {
return mode return mode
// I2C SCL // I2C SCL
case PinModeI2CSCL: case pinModeI2CSCL:
var mode uint32 var mode uint32
switch p { switch p {
case PA12: // LPI2C4 SCL on PA12 alternate function 0 case PA12: // LPI2C4 SCL on PA12 alternate function 0
@@ -898,7 +902,7 @@ func (a ADC) Configure(config ADCConfig) {
defaultSamples = uint32(4) defaultSamples = uint32(4)
) )
a.Pin.Configure(PinConfig{Mode: PinInputAnalog}) a.Pin.Configure(PinConfig{Mode: pinInputAnalog})
resolution, samples := config.Resolution, config.Samples resolution, samples := config.Resolution, config.Samples
if 0 == resolution { if 0 == resolution {
+9 -18
View File
@@ -10,15 +10,6 @@ import (
"errors" "errors"
) )
const (
TWI_FREQ_BUS = 24000000 // LPI2C root clock is on 24 MHz OSC
TWI_FREQ_100KHZ = 100000 // StandardMode (100 kHz)
TWI_FREQ_400KHZ = 400000 // FastMode (400 kHz)
TWI_FREQ_1MHZ = 1000000 // FastModePlus (1 MHz)
TWI_FREQ_5MHZ = 5000000 // UltraFastMode (5 MHz)
TWI_FREQ_DEFAULT = TWI_FREQ_100KHZ // default to StandardMode (100 kHz)
)
var ( var (
errI2CWriteTimeout = errors.New("I2C timeout during write") errI2CWriteTimeout = errors.New("I2C timeout during write")
errI2CReadTimeout = errors.New("I2C timeout during read") errI2CReadTimeout = errors.New("I2C timeout during read")
@@ -165,8 +156,8 @@ func (i2c *I2C) Configure(config I2CConfig) {
sda, scl := i2c.setPins(config) sda, scl := i2c.setPins(config)
// configure the mux and pad control registers // configure the mux and pad control registers
sda.Configure(PinConfig{Mode: PinModeI2CSDA}) sda.Configure(PinConfig{Mode: pinModeI2CSDA})
scl.Configure(PinConfig{Mode: PinModeI2CSCL}) scl.Configure(PinConfig{Mode: pinModeI2CSCL})
// configure the mux input selector // configure the mux input selector
i2c.muxSDA.connect() i2c.muxSDA.connect()
@@ -174,7 +165,7 @@ func (i2c *I2C) Configure(config I2CConfig) {
freq := config.Frequency freq := config.Frequency
if 0 == freq { if 0 == freq {
freq = TWI_FREQ_DEFAULT freq = 100 * KHz
} }
// reset clock and registers, and enable LPI2C module interface // reset clock and registers, and enable LPI2C module interface
@@ -305,7 +296,7 @@ func (i2c *I2C) setFrequency(freq uint32) {
wasEnabled := i2c.Bus.MCR.HasBits(nxp.LPI2C_MCR_MEN) wasEnabled := i2c.Bus.MCR.HasBits(nxp.LPI2C_MCR_MEN)
i2c.Bus.MCR.ClearBits(nxp.LPI2C_MCR_MEN) i2c.Bus.MCR.ClearBits(nxp.LPI2C_MCR_MEN)
// baud rate = (TWI_FREQ_BUS/(2^pre))/(CLKLO+1 + CLKHI+1 + FLOOR((2+FILTSCL)/(2^pre))) // baud rate = (24MHz/(2^pre))/(CLKLO+1 + CLKHI+1 + FLOOR((2+FILTSCL)/(2^pre)))
// assume: CLKLO=2*CLKHI, SETHOLD=CLKHI, DATAVD=CLKHI/2 // assume: CLKLO=2*CLKHI, SETHOLD=CLKHI, DATAVD=CLKHI/2
for pre := uint32(1); pre <= 128; pre *= 2 { for pre := uint32(1); pre <= 128; pre *= 2 {
if bestError == 0 { if bestError == 0 {
@@ -314,9 +305,9 @@ func (i2c *I2C) setFrequency(freq uint32) {
for clkHi := uint32(1); clkHi < 32; clkHi++ { for clkHi := uint32(1); clkHi < 32; clkHi++ {
var absError, rate uint32 var absError, rate uint32
if clkHi == 1 { if clkHi == 1 {
rate = (TWI_FREQ_BUS / pre) / (1 + 3 + 2 + 2/pre) rate = (24 * MHz / pre) / (1 + 3 + 2 + 2/pre)
} else { } else {
rate = (TWI_FREQ_BUS / pre) / (3*clkHi + 2 + 2/pre) rate = (24 * MHz / pre) / (3*clkHi + 2 + 2/pre)
} }
if freq > rate { if freq > rate {
absError = freq - rate absError = freq - rate
@@ -370,15 +361,15 @@ func (i2c *I2C) setFrequency(freq uint32) {
mcfgr2, mcfgr3 uint32 mcfgr2, mcfgr3 uint32
) )
const i2cClockStretchTimeout = 15000 // microseconds const i2cClockStretchTimeout = 15000 // microseconds
if freq >= TWI_FREQ_5MHZ { if freq >= 5*MHz {
// I2C UltraFastMode 5 MHz // I2C UltraFastMode 5 MHz
mcfgr2 = 0 // disable glitch filters and timeout for UltraFastMode mcfgr2 = 0 // disable glitch filters and timeout for UltraFastMode
mcfgr3 = 0 // mcfgr3 = 0 //
} else if freq >= TWI_FREQ_1MHZ { } else if freq >= 1*MHz {
// I2C FastModePlus 1 MHz // I2C FastModePlus 1 MHz
mcfgr2 = filtsda(1) | filtscl(1) | busidle(2400) // 100us timeout mcfgr2 = filtsda(1) | filtscl(1) | busidle(2400) // 100us timeout
mcfgr3 = pinlow(i2cClockStretchTimeout*24/256 + 1) mcfgr3 = pinlow(i2cClockStretchTimeout*24/256 + 1)
} else if freq >= TWI_FREQ_400KHZ { } else if freq >= 400*KHz {
// I2C FastMode 400 kHz // I2C FastMode 400 kHz
mcfgr2 = filtsda(2) | filtscl(2) | busidle(3600) // 150us timeout mcfgr2 = filtsda(2) | filtscl(2) | busidle(3600) // 150us timeout
mcfgr3 = pinlow(i2cClockStretchTimeout*24/256 + 1) mcfgr3 = pinlow(i2cClockStretchTimeout*24/256 + 1)
+4 -4
View File
@@ -77,10 +77,10 @@ func (spi *SPI) Configure(config SPIConfig) {
spi.sdi, spi.sdo, spi.sck, spi.cs = config.getPins() spi.sdi, spi.sdo, spi.sck, spi.cs = config.getPins()
// configure the mux and pad control registers // configure the mux and pad control registers
spi.sdi.Configure(PinConfig{Mode: PinModeSPISDI}) spi.sdi.Configure(PinConfig{Mode: pinModeSPISDI})
spi.sdo.Configure(PinConfig{Mode: PinModeSPISDO}) spi.sdo.Configure(PinConfig{Mode: pinModeSPISDO})
spi.sck.Configure(PinConfig{Mode: PinModeSPICLK}) spi.sck.Configure(PinConfig{Mode: pinModeSPICLK})
spi.cs.Configure(PinConfig{Mode: PinModeSPICS}) spi.cs.Configure(PinConfig{Mode: pinModeSPICS})
// configure the mux input selector // configure the mux input selector
spi.muxSDI.connect() spi.muxSDI.connect()
+4 -4
View File
@@ -68,8 +68,8 @@ func (uart *UART) Configure(config UARTConfig) {
uart.tx = config.TX uart.tx = config.TX
// configure the mux and pad control registers // configure the mux and pad control registers
uart.rx.Configure(PinConfig{Mode: PinModeUARTRX}) uart.rx.Configure(PinConfig{Mode: pinModeUARTRX})
uart.tx.Configure(PinConfig{Mode: PinModeUARTTX}) uart.tx.Configure(PinConfig{Mode: pinModeUARTTX})
// configure the mux input selector // configure the mux input selector
uart.muxRX.connect() uart.muxRX.connect()
@@ -159,8 +159,8 @@ func (uart *UART) Disable() {
uart.Bus.CTRL.ClearBits(nxp.LPUART_CTRL_TE | nxp.LPUART_CTRL_RE) uart.Bus.CTRL.ClearBits(nxp.LPUART_CTRL_TE | nxp.LPUART_CTRL_RE)
// put pins back into GPIO mode // put pins back into GPIO mode
uart.rx.Configure(PinConfig{Mode: PinInputPullUp}) uart.rx.Configure(PinConfig{Mode: PinInputPullup})
uart.tx.Configure(PinConfig{Mode: PinInputPullUp}) uart.tx.Configure(PinConfig{Mode: PinInputPullup})
} }
uart.configured = false uart.configured = false
} }
+40 -7
View File
@@ -5,15 +5,10 @@ package machine
import ( import (
"device/nrf" "device/nrf"
"errors"
"runtime/interrupt" "runtime/interrupt"
"unsafe" "unsafe"
) )
var (
ErrTxInvalidSliceSize = errors.New("SPI write and read slices must be same size")
)
const deviceName = nrf.Device const deviceName = nrf.Device
const ( const (
@@ -230,7 +225,7 @@ func (i2c *I2C) Configure(config I2CConfig) error {
// Default I2C bus speed is 100 kHz. // Default I2C bus speed is 100 kHz.
if config.Frequency == 0 { if config.Frequency == 0 {
config.Frequency = TWI_FREQ_100KHZ config.Frequency = 100 * KHz
} }
// Default I2C pins if not set. // Default I2C pins if not set.
if config.SDA == 0 && config.SCL == 0 { if config.SDA == 0 && config.SCL == 0 {
@@ -253,7 +248,7 @@ func (i2c *I2C) Configure(config I2CConfig) error {
(nrf.GPIO_PIN_CNF_DRIVE_S0D1 << nrf.GPIO_PIN_CNF_DRIVE_Pos) | (nrf.GPIO_PIN_CNF_DRIVE_S0D1 << nrf.GPIO_PIN_CNF_DRIVE_Pos) |
(nrf.GPIO_PIN_CNF_SENSE_Disabled << nrf.GPIO_PIN_CNF_SENSE_Pos)) (nrf.GPIO_PIN_CNF_SENSE_Disabled << nrf.GPIO_PIN_CNF_SENSE_Pos))
if config.Frequency == TWI_FREQ_400KHZ { if config.Frequency >= 400*KHz {
i2c.Bus.FREQUENCY.Set(nrf.TWI_FREQUENCY_FREQUENCY_K400) i2c.Bus.FREQUENCY.Set(nrf.TWI_FREQUENCY_FREQUENCY_K400)
} else { } else {
i2c.Bus.FREQUENCY.Set(nrf.TWI_FREQUENCY_FREQUENCY_K100) i2c.Bus.FREQUENCY.Set(nrf.TWI_FREQUENCY_FREQUENCY_K100)
@@ -350,3 +345,41 @@ func (i2c *I2C) readByte() (byte, error) {
i2c.Bus.EVENTS_RXDREADY.Set(0) i2c.Bus.EVENTS_RXDREADY.Set(0)
return byte(i2c.Bus.RXD.Get()), nil return byte(i2c.Bus.RXD.Get()), nil
} }
var rngStarted = false
// GetRNG returns 32 bits of non-deterministic random data based on internal thermal noise.
// According to Nordic's documentation, the random output is suitable for cryptographic purposes.
func GetRNG() (ret uint32, err error) {
// There's no apparent way to check the status of the RNG peripheral's task, so simply start it
// to avoid deadlocking while waiting for output.
if !rngStarted {
nrf.RNG.TASKS_START.Set(1)
nrf.RNG.SetCONFIG_DERCEN(nrf.RNG_CONFIG_DERCEN_Enabled)
rngStarted = true
}
// The RNG returns one byte at a time, so stack up four bytes into a single uint32 for return.
for i := 0; i < 4; i++ {
// Wait for data to be ready.
for nrf.RNG.EVENTS_VALRDY.Get() == 0 {
}
// Append random byte to output.
ret = (ret << 8) ^ nrf.RNG.GetVALUE()
// Unset the EVENTS_VALRDY register to avoid reading the same random output twice.
nrf.RNG.EVENTS_VALRDY.Set(0)
}
return ret, nil
}
// ReadTemperature reads the silicon die temperature of the chip. The return
// value is in milli-celsius.
func ReadTemperature() int32 {
nrf.TEMP.TASKS_START.Set(1)
for nrf.TEMP.EVENTS_DATARDY.Get() == 0 {
}
temp := int32(nrf.TEMP.TEMP.Get()) * 250 // the returned value is in units of 0.25°C
nrf.TEMP.EVENTS_DATARDY.Set(0)
return temp
}
@@ -9,16 +9,16 @@ import (
) )
const ( const (
DFU_MAGIC_SERIAL_ONLY_RESET = 0x4e dfuMagicSerialOnlyReset = 0x4e
DFU_MAGIC_UF2_RESET = 0x57 dfuMagicUF2Reset = 0x57
DFU_MAGIC_OTA_RESET = 0xA8 dfuMagicOTAReset = 0xA8
) )
// EnterSerialBootloader resets the chip into the serial bootloader. After // EnterSerialBootloader resets the chip into the serial bootloader. After
// reset, it can be flashed using serial/nrfutil. // reset, it can be flashed using serial/nrfutil.
func EnterSerialBootloader() { func EnterSerialBootloader() {
arm.DisableInterrupts() arm.DisableInterrupts()
nrf.POWER.GPREGRET.Set(DFU_MAGIC_SERIAL_ONLY_RESET) nrf.POWER.GPREGRET.Set(dfuMagicSerialOnlyReset)
arm.SystemReset() arm.SystemReset()
} }
@@ -26,7 +26,7 @@ func EnterSerialBootloader() {
// can be flashed via nrfutil or by copying a UF2 file to the mass storage device // can be flashed via nrfutil or by copying a UF2 file to the mass storage device
func EnterUF2Bootloader() { func EnterUF2Bootloader() {
arm.DisableInterrupts() arm.DisableInterrupts()
nrf.POWER.GPREGRET.Set(DFU_MAGIC_UF2_RESET) nrf.POWER.GPREGRET.Set(dfuMagicUF2Reset)
arm.SystemReset() arm.SystemReset()
} }
@@ -34,6 +34,6 @@ func EnterUF2Bootloader() {
// flashed via an OTA update // flashed via an OTA update
func EnterOTABootloader() { func EnterOTABootloader() {
arm.DisableInterrupts() arm.DisableInterrupts()
nrf.POWER.GPREGRET.Set(DFU_MAGIC_OTA_RESET) nrf.POWER.GPREGRET.Set(dfuMagicOTAReset)
arm.SystemReset() arm.SystemReset()
} }
+10 -4
View File
@@ -42,13 +42,19 @@ const deviceName = nxp.Device
const ( const (
PinInput PinMode = iota PinInput PinMode = iota
PinInputPullUp PinInputPullup
PinInputPullDown PinInputPulldown
PinOutput PinOutput
PinOutputOpenDrain PinOutputOpenDrain
PinDisable PinDisable
) )
// Deprecated: use PinInputPullup and PinInputPulldown instead.
const (
PinInputPullUp = PinInputPullup
PinInputPullDown = PinInputPulldown
)
const ( const (
PA00 Pin = iota PA00 Pin = iota
PA01 PA01
@@ -223,11 +229,11 @@ func (p Pin) Configure(config PinConfig) {
gpio.PDDR.ClearBits(1 << pos) gpio.PDDR.ClearBits(1 << pos)
pcr.Set((1 << nxp.PORT_PCR0_MUX_Pos)) pcr.Set((1 << nxp.PORT_PCR0_MUX_Pos))
case PinInputPullUp: case PinInputPullup:
gpio.PDDR.ClearBits(1 << pos) gpio.PDDR.ClearBits(1 << pos)
pcr.Set((1 << nxp.PORT_PCR0_MUX_Pos) | nxp.PORT_PCR0_PE | nxp.PORT_PCR0_PS) pcr.Set((1 << nxp.PORT_PCR0_MUX_Pos) | nxp.PORT_PCR0_PE | nxp.PORT_PCR0_PS)
case PinInputPullDown: case PinInputPulldown:
gpio.PDDR.ClearBits(1 << pos) gpio.PDDR.ClearBits(1 << pos)
pcr.Set((1 << nxp.PORT_PCR0_MUX_Pos) | nxp.PORT_PCR0_PE) pcr.Set((1 << nxp.PORT_PCR0_MUX_Pos) | nxp.PORT_PCR0_PE)
+2 -2
View File
@@ -203,8 +203,8 @@ func (u *UART) Disable() {
u.C2.Set(0) u.C2.Set(0)
// reconfigure pin // reconfigure pin
u.DefaultRX.Configure(PinConfig{Mode: PinInputPullUp}) u.DefaultRX.Configure(PinConfig{Mode: PinInputPullup})
u.DefaultTX.Configure(PinConfig{Mode: PinInputPullUp}) u.DefaultTX.Configure(PinConfig{Mode: PinInputPullup})
// clear flags // clear flags
u.S1.Get() u.S1.Get()
+30 -30
View File
@@ -11,36 +11,36 @@ const deviceName = rp.Device
const ( const (
// GPIO pins // GPIO pins
GPIO0 Pin = 0 GPIO0 Pin = 0 // peripherals: PWM0 channel A
GPIO1 Pin = 1 GPIO1 Pin = 1 // peripherals: PWM0 channel B
GPIO2 Pin = 2 GPIO2 Pin = 2 // peripherals: PWM1 channel A
GPIO3 Pin = 3 GPIO3 Pin = 3 // peripherals: PWM1 channel B
GPIO4 Pin = 4 GPIO4 Pin = 4 // peripherals: PWM2 channel A
GPIO5 Pin = 5 GPIO5 Pin = 5 // peripherals: PWM2 channel B
GPIO6 Pin = 6 GPIO6 Pin = 6 // peripherals: PWM3 channel A
GPIO7 Pin = 7 GPIO7 Pin = 7 // peripherals: PWM3 channel B
GPIO8 Pin = 8 GPIO8 Pin = 8 // peripherals: PWM4 channel A
GPIO9 Pin = 9 GPIO9 Pin = 9 // peripherals: PWM4 channel B
GPIO10 Pin = 10 GPIO10 Pin = 10 // peripherals: PWM5 channel A
GPIO11 Pin = 11 GPIO11 Pin = 11 // peripherals: PWM5 channel B
GPIO12 Pin = 12 GPIO12 Pin = 12 // peripherals: PWM6 channel A
GPIO13 Pin = 13 GPIO13 Pin = 13 // peripherals: PWM6 channel B
GPIO14 Pin = 14 GPIO14 Pin = 14 // peripherals: PWM7 channel A
GPIO15 Pin = 15 GPIO15 Pin = 15 // peripherals: PWM7 channel B
GPIO16 Pin = 16 GPIO16 Pin = 16 // peripherals: PWM0 channel A
GPIO17 Pin = 17 GPIO17 Pin = 17 // peripherals: PWM0 channel B
GPIO18 Pin = 18 GPIO18 Pin = 18 // peripherals: PWM1 channel A
GPIO19 Pin = 19 GPIO19 Pin = 19 // peripherals: PWM1 channel B
GPIO20 Pin = 20 GPIO20 Pin = 20 // peripherals: PWM2 channel A
GPIO21 Pin = 21 GPIO21 Pin = 21 // peripherals: PWM2 channel B
GPIO22 Pin = 22 GPIO22 Pin = 22 // peripherals: PWM3 channel A
GPIO23 Pin = 23 GPIO23 Pin = 23 // peripherals: PWM3 channel B
GPIO24 Pin = 24 GPIO24 Pin = 24 // peripherals: PWM4 channel A
GPIO25 Pin = 25 GPIO25 Pin = 25 // peripherals: PWM4 channel B
GPIO26 Pin = 26 GPIO26 Pin = 26 // peripherals: PWM5 channel A
GPIO27 Pin = 27 GPIO27 Pin = 27 // peripherals: PWM5 channel B
GPIO28 Pin = 28 GPIO28 Pin = 28 // peripherals: PWM6 channel A
GPIO29 Pin = 29 GPIO29 Pin = 29 // peripherals: PWM6 channel B
// Analog pins // Analog pins
ADC0 Pin = GPIO26 ADC0 Pin = GPIO26
+15 -14
View File
@@ -17,8 +17,8 @@ const (
adc0_CH ADCChannel = iota adc0_CH ADCChannel = iota
adc1_CH adc1_CH
adc2_CH adc2_CH
adc3_CH // Note: GPIO29 not broken out on pico board adc3_CH // Note: GPIO29 not broken out on pico board
ADC_TEMP_SENSOR // Internal temperature sensor channel adcTempSensor // Internal temperature sensor channel
) )
// Used to serialise ADC sampling // Used to serialise ADC sampling
@@ -75,19 +75,17 @@ func (a ADC) GetADCChannel() (c ADCChannel, err error) {
return c, err return c, err
} }
// Configure sets the channel's associated pin to analog input mode or powers on the temperature sensor for ADC_TEMP_SENSOR. // Configure sets the channel's associated pin to analog input mode.
// The powered on temperature sensor increases ADC_AVDD current by approximately 40 μA. // The powered on temperature sensor increases ADC_AVDD current by approximately 40 μA.
func (c ADCChannel) Configure(config ADCConfig) error { func (c ADCChannel) Configure(config ADCConfig) error {
if config.Reference != 0 { if config.Reference != 0 {
adcAref = config.Reference adcAref = config.Reference
} }
if p, err := c.Pin(); err == nil { p, err := c.Pin()
p.Configure(PinConfig{Mode: PinAnalog}) if err != nil {
} return err
if c == ADC_TEMP_SENSOR {
// Enable temperature sensor bias source
rp.ADC.CS.SetBits(rp.ADC_CS_TS_EN)
} }
p.Configure(PinConfig{Mode: pinAnalog})
return nil return nil
} }
@@ -112,13 +110,16 @@ func (c ADCChannel) getVoltage() uint32 {
} }
// ReadTemperature does a one-shot sample of the internal temperature sensor and returns a milli-celsius reading. // ReadTemperature does a one-shot sample of the internal temperature sensor and returns a milli-celsius reading.
// Only works on the ADC_TEMP_SENSOR channel. aka AINSEL=4. Other channels will return 0 func ReadTemperature() (millicelsius int32) {
func (c ADCChannel) ReadTemperature() (millicelsius uint32) { if rp.ADC.CS.Get()&rp.ADC_CS_EN == 0 {
if c != ADC_TEMP_SENSOR { InitADC()
return
} }
// Enable temperature sensor bias source
rp.ADC.CS.SetBits(rp.ADC_CS_TS_EN)
// T = 27 - (ADC_voltage - 0.706)/0.001721 // T = 27 - (ADC_voltage - 0.706)/0.001721
return (27000<<16 - (c.getVoltage()-706<<16)*581) >> 16 return (27000<<16 - (int32(adcTempSensor.getVoltage())-706<<16)*581) >> 16
} }
// waitForReady spins waiting for the ADC peripheral to become ready. // waitForReady spins waiting for the ADC peripheral to become ready.
-5
View File
@@ -10,11 +10,6 @@ import (
"unsafe" "unsafe"
) )
const (
KHz = 1000
MHz = 1000000
)
func CPUFrequency() uint32 { func CPUFrequency() uint32 {
return 125 * MHz return 125 * MHz
} }
+13 -15
View File
@@ -81,11 +81,13 @@ const (
PinInput PinInput
PinInputPulldown PinInputPulldown
PinInputPullup PinInputPullup
PinAnalog
PinUART // internal pin modes
PinPWM pinAnalog
PinI2C pinUART
PinSPI pinPWM
pinI2C
pinSPI
) )
func (p Pin) PortMaskSet() (*uint32, uint32) { func (p Pin) PortMaskSet() (*uint32, uint32) {
@@ -188,20 +190,20 @@ func (p Pin) Configure(config PinConfig) {
case PinInputPullup: case PinInputPullup:
p.setFunc(fnSIO) p.setFunc(fnSIO)
p.pullup() p.pullup()
case PinAnalog: case pinAnalog:
p.setFunc(fnNULL) p.setFunc(fnNULL)
p.pulloff() p.pulloff()
case PinUART: case pinUART:
p.setFunc(fnUART) p.setFunc(fnUART)
case PinPWM: case pinPWM:
p.setFunc(fnPWM) p.setFunc(fnPWM)
case PinI2C: case pinI2C:
// IO config according to 4.3.1.3 of rp2040 datasheet. // IO config according to 4.3.1.3 of rp2040 datasheet.
p.setFunc(fnI2C) p.setFunc(fnI2C)
p.pullup() p.pullup()
p.setSchmitt(true) p.setSchmitt(true)
p.setSlew(false) p.setSlew(false)
case PinSPI: case pinSPI:
p.setFunc(fnSPI) p.setFunc(fnSPI)
} }
} }
@@ -226,12 +228,8 @@ type PinChange uint8
// Pin change interrupt constants for SetInterrupt. // Pin change interrupt constants for SetInterrupt.
const ( const (
// PinLevelLow triggers whenever pin is at a low (around 0V) logic level.
PinLevelLow PinChange = 1 << iota
// PinLevelLow triggers whenever pin is at a high (around 3V) logic level.
PinLevelHigh
// Edge falling // Edge falling
PinFalling PinFalling PinChange = 4 << iota
// Edge rising // Edge rising
PinRising PinRising
) )
+2 -2
View File
@@ -105,8 +105,8 @@ func (i2c *I2C) Configure(config I2CConfig) error {
if config.Frequency == 0 { if config.Frequency == 0 {
config.Frequency = defaultBaud config.Frequency = defaultBaud
} }
config.SDA.Configure(PinConfig{PinI2C}) config.SDA.Configure(PinConfig{pinI2C})
config.SCL.Configure(PinConfig{PinI2C}) config.SCL.Configure(PinConfig{pinI2C})
return i2c.init(config) return i2c.init(config)
} }
+1 -1
View File
@@ -92,7 +92,7 @@ func (pwm *pwmGroup) Channel(pin Pin) (channel uint8, err error) {
if pin > maxPWMPins || pwmGPIOToSlice(pin) != pwm.peripheral() { if pin > maxPWMPins || pwmGPIOToSlice(pin) != pwm.peripheral() {
return 3, ErrInvalidOutputPin return 3, ErrInvalidOutputPin
} }
pin.Configure(PinConfig{PinPWM}) pin.Configure(PinConfig{pinPWM})
return pwmGPIOToChannel(pin), nil return pwmGPIOToChannel(pin), nil
} }
+42
View File
@@ -0,0 +1,42 @@
//go:build rp2040
// +build rp2040
// Implementation based on code located here:
// https://github.com/raspberrypi/pico-sdk/blob/master/src/rp2_common/pico_lwip/random.c
package machine
import (
"device/rp"
)
const numberOfCycles = 32
// GetRNG returns 32 bits of semi-random data based on ring oscillator.
//
// Unlike some other implementations of GetRNG, these random numbers are not
// cryptographically secure and must not be used for cryptographic operations
// (nonces, etc).
func GetRNG() (uint32, error) {
var val uint32
for i := 0; i < 4; i++ {
val = (val << 8) | uint32(roscRandByte())
}
return val, nil
}
var randomByte uint8
func roscRandByte() uint8 {
var poly uint8
for i := 0; i < numberOfCycles; i++ {
if randomByte&0x80 != 0 {
poly = 0x35
} else {
poly = 0
}
randomByte = ((randomByte << 1) | uint8(rp.ROSC.GetRANDOMBIT()) ^ poly)
// TODO: delay a little because the random bit is a little slow
}
return randomByte
}
+3 -4
View File
@@ -38,10 +38,9 @@ type SPIConfig struct {
} }
var ( var (
ErrLSBNotSupported = errors.New("SPI LSB unsupported on PL022") ErrLSBNotSupported = errors.New("SPI LSB unsupported on PL022")
ErrTxInvalidSliceSize = errors.New("SPI write and read slices must be same size") ErrSPITimeout = errors.New("SPI timeout")
ErrSPITimeout = errors.New("SPI timeout") ErrSPIBaud = errors.New("SPI baud too low or above 66.5Mhz")
ErrSPIBaud = errors.New("SPI baud too low or above 66.5Mhz")
) )
type SPI struct { type SPI struct {
+2 -2
View File
@@ -42,8 +42,8 @@ func (uart *UART) Configure(config UARTConfig) error {
rp.UART0_UARTCR_TXE) rp.UART0_UARTCR_TXE)
// set GPIO mux to UART for the pins // set GPIO mux to UART for the pins
config.TX.Configure(PinConfig{Mode: PinUART}) config.TX.Configure(PinConfig{Mode: pinUART})
config.RX.Configure(PinConfig{Mode: PinUART}) config.RX.Configure(PinConfig{Mode: pinUART})
// Enable RX IRQ. // Enable RX IRQ.
uart.Interrupt.SetPriority(0x80) uart.Interrupt.SetPriority(0x80)
+1 -1
View File
@@ -41,7 +41,7 @@ func InitADC() {
// Configure configures an ADC pin to be able to read analog data. // Configure configures an ADC pin to be able to read analog data.
func (a ADC) Configure(ADCConfig) { func (a ADC) Configure(ADCConfig) {
a.Pin.Configure(PinConfig{Mode: PinInputModeAnalog}) a.Pin.Configure(PinConfig{Mode: pinInputModeAnalog})
// set sample time // set sample time
ch := a.getChannel() ch := a.getChannel()
+1 -1
View File
@@ -36,7 +36,7 @@ func InitADC() {
// Configure configures an ADC pin to be able to read analog data. // Configure configures an ADC pin to be able to read analog data.
func (a ADC) Configure(ADCConfig) { func (a ADC) Configure(ADCConfig) {
a.Pin.ConfigureAltFunc(PinConfig{Mode: PinInputAnalog}, 0) a.Pin.ConfigureAltFunc(PinConfig{Mode: pinInputAnalog}, 0)
// set sample time // set sample time
ch := a.getChannel() ch := a.getChannel()
+1 -1
View File
@@ -137,7 +137,7 @@ func (i2c *I2C) Configure(config I2CConfig) error {
// default to 100 kHz (Sm, standard mode) if no frequency is set // default to 100 kHz (Sm, standard mode) if no frequency is set
if config.Frequency == 0 { if config.Frequency == 0 {
config.Frequency = TWI_FREQ_100KHZ config.Frequency = 100 * KHz
} }
// configure I2C input clock // configure I2C input clock
+2 -2
View File
@@ -102,8 +102,8 @@ func (i2c *I2C) Tx(addr uint16, w, r []byte) error {
} }
func (i2c *I2C) configurePins(config I2CConfig) { func (i2c *I2C) configurePins(config I2CConfig) {
config.SCL.ConfigureAltFunc(PinConfig{Mode: PinModeI2CSCL}, i2c.AltFuncSelector) config.SCL.ConfigureAltFunc(PinConfig{Mode: pinModeI2CSCL}, i2c.AltFuncSelector)
config.SDA.ConfigureAltFunc(PinConfig{Mode: PinModeI2CSDA}, i2c.AltFuncSelector) config.SDA.ConfigureAltFunc(PinConfig{Mode: pinModeI2CSDA}, i2c.AltFuncSelector)
} }
func (i2c *I2C) controllerTransmit(addr uint16, w []byte) error { func (i2c *I2C) controllerTransmit(addr uint16, w []byte) error {
+20 -21
View File
@@ -14,29 +14,28 @@ import (
const ( const (
// Mode Flag // Mode Flag
PinOutput PinMode = 0 PinOutput PinMode = 0
PinInput PinMode = PinInputFloating PinInput PinMode = 1
PinInputFloating PinMode = 1
PinInputPulldown PinMode = 2 PinInputPulldown PinMode = 2
PinInputPullup PinMode = 3 PinInputPullup PinMode = 3
// for UART // for UART
PinModeUARTTX PinMode = 4 pinModeUARTTX PinMode = 4
PinModeUARTRX PinMode = 5 pinModeUARTRX PinMode = 5
// for I2C // for I2C
PinModeI2CSCL PinMode = 6 pinModeI2CSCL PinMode = 6
PinModeI2CSDA PinMode = 7 pinModeI2CSDA PinMode = 7
// for SPI // for SPI
PinModeSPICLK PinMode = 8 pinModeSPICLK PinMode = 8
PinModeSPISDO PinMode = 9 pinModeSPISDO PinMode = 9
PinModeSPISDI PinMode = 10 pinModeSPISDI PinMode = 10
// for analog/ADC // for analog/ADC
PinInputAnalog PinMode = 11 pinInputAnalog PinMode = 11
// for PWM // for PWM
PinModePWMOutput PinMode = 12 pinModePWMOutput PinMode = 12
) )
// Define several bitfields that have different names across chip families but // Define several bitfields that have different names across chip families but
@@ -83,7 +82,7 @@ func (p Pin) ConfigureAltFunc(config PinConfig, altFunc uint8) {
switch config.Mode { switch config.Mode {
// GPIO // GPIO
case PinInputFloating: case PinInput:
port.MODER.ReplaceBits(gpioModeInput, gpioModeMask, pos) port.MODER.ReplaceBits(gpioModeInput, gpioModeMask, pos)
port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos) port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)
case PinInputPulldown: case PinInputPulldown:
@@ -97,24 +96,24 @@ func (p Pin) ConfigureAltFunc(config PinConfig, altFunc uint8) {
port.OSPEEDR.ReplaceBits(gpioOutputSpeedHigh, gpioOutputSpeedMask, pos) port.OSPEEDR.ReplaceBits(gpioOutputSpeedHigh, gpioOutputSpeedMask, pos)
// UART // UART
case PinModeUARTTX: case pinModeUARTTX:
port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos) port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
port.OSPEEDR.ReplaceBits(gpioOutputSpeedHigh, gpioOutputSpeedMask, pos) port.OSPEEDR.ReplaceBits(gpioOutputSpeedHigh, gpioOutputSpeedMask, pos)
port.PUPDR.ReplaceBits(gpioPullUp, gpioPullMask, pos) port.PUPDR.ReplaceBits(gpioPullUp, gpioPullMask, pos)
p.SetAltFunc(altFunc) p.SetAltFunc(altFunc)
case PinModeUARTRX: case pinModeUARTRX:
port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos) port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos) port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)
p.SetAltFunc(altFunc) p.SetAltFunc(altFunc)
// I2C // I2C
case PinModeI2CSCL: case pinModeI2CSCL:
port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos) port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
port.OTYPER.ReplaceBits(stm32.GPIO_OTYPER_OT0_OpenDrain, stm32.GPIO_OTYPER_OT0_Msk, pos/2) port.OTYPER.ReplaceBits(stm32.GPIO_OTYPER_OT0_OpenDrain, stm32.GPIO_OTYPER_OT0_Msk, pos/2)
port.OSPEEDR.ReplaceBits(gpioOutputSpeedLow, gpioOutputSpeedMask, pos) port.OSPEEDR.ReplaceBits(gpioOutputSpeedLow, gpioOutputSpeedMask, pos)
port.PUPDR.ReplaceBits(gpioPullUp, gpioPullMask, pos) port.PUPDR.ReplaceBits(gpioPullUp, gpioPullMask, pos)
p.SetAltFunc(altFunc) p.SetAltFunc(altFunc)
case PinModeI2CSDA: case pinModeI2CSDA:
port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos) port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
port.OTYPER.ReplaceBits(stm32.GPIO_OTYPER_OT0_OpenDrain, stm32.GPIO_OTYPER_OT0_Msk, pos/2) port.OTYPER.ReplaceBits(stm32.GPIO_OTYPER_OT0_OpenDrain, stm32.GPIO_OTYPER_OT0_Msk, pos/2)
port.OSPEEDR.ReplaceBits(gpioOutputSpeedLow, gpioOutputSpeedMask, pos) port.OSPEEDR.ReplaceBits(gpioOutputSpeedLow, gpioOutputSpeedMask, pos)
@@ -122,31 +121,31 @@ func (p Pin) ConfigureAltFunc(config PinConfig, altFunc uint8) {
p.SetAltFunc(altFunc) p.SetAltFunc(altFunc)
// SPI // SPI
case PinModeSPICLK: case pinModeSPICLK:
port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos) port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
port.OSPEEDR.ReplaceBits(gpioOutputSpeedHigh, gpioOutputSpeedMask, pos) port.OSPEEDR.ReplaceBits(gpioOutputSpeedHigh, gpioOutputSpeedMask, pos)
port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos) port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)
p.SetAltFunc(altFunc) p.SetAltFunc(altFunc)
case PinModeSPISDO: case pinModeSPISDO:
port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos) port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
port.OSPEEDR.ReplaceBits(gpioOutputSpeedLow, gpioOutputSpeedMask, pos) port.OSPEEDR.ReplaceBits(gpioOutputSpeedLow, gpioOutputSpeedMask, pos)
port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos) port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)
p.SetAltFunc(altFunc) p.SetAltFunc(altFunc)
case PinModeSPISDI: case pinModeSPISDI:
port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos) port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
port.OSPEEDR.ReplaceBits(gpioOutputSpeedLow, gpioOutputSpeedMask, pos) port.OSPEEDR.ReplaceBits(gpioOutputSpeedLow, gpioOutputSpeedMask, pos)
port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos) port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)
p.SetAltFunc(altFunc) p.SetAltFunc(altFunc)
// PWM // PWM
case PinModePWMOutput: case pinModePWMOutput:
port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos) port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
port.OSPEEDR.ReplaceBits(gpioOutputSpeedHigh, gpioOutputSpeedMask, pos) port.OSPEEDR.ReplaceBits(gpioOutputSpeedHigh, gpioOutputSpeedMask, pos)
port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos) port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)
p.SetAltFunc(altFunc) p.SetAltFunc(altFunc)
// ADC // ADC
case PinInputAnalog: case pinInputAnalog:
port.MODER.ReplaceBits(gpioModeAnalog, gpioModeMask, pos) port.MODER.ReplaceBits(gpioModeAnalog, gpioModeMask, pos)
} }
} }
+1 -1
View File
@@ -183,7 +183,7 @@ func (t *TIM) Channel(pin Pin) (uint8, error) {
for _, p := range ch.Pins { for _, p := range ch.Pins {
if p.Pin == pin { if p.Pin == pin {
t.configurePin(uint8(chi), p) t.configurePin(uint8(chi), p)
//p.Pin.ConfigureAltFunc(PinConfig{Mode: PinModePWMOutput}, p.AltFunc) //p.Pin.ConfigureAltFunc(PinConfig{Mode: pinModePWMOutput}, p.AltFunc)
return uint8(chi), nil return uint8(chi), nil
} }
} }
+1 -1
View File
@@ -7,5 +7,5 @@ package machine
// register (most MCUs except STM32F1 series). // register (most MCUs except STM32F1 series).
func (t *TIM) configurePin(channel uint8, pf PinFunction) { func (t *TIM) configurePin(channel uint8, pf PinFunction) {
pf.Pin.ConfigureAltFunc(PinConfig{Mode: PinModePWMOutput}, pf.AltFunc) pf.Pin.ConfigureAltFunc(PinConfig{Mode: pinModePWMOutput}, pf.AltFunc)
} }
+19 -19
View File
@@ -29,20 +29,20 @@ const (
PinOutput50MHz PinMode = 3 // Output mode, max speed 50MHz PinOutput50MHz PinMode = 3 // Output mode, max speed 50MHz
PinOutput PinMode = PinOutput2MHz PinOutput PinMode = PinOutput2MHz
PinInputModeAnalog PinMode = 0 // Input analog mode pinInputModeAnalog PinMode = 0 // Input analog mode
PinInputModeFloating PinMode = 4 // Input floating mode pinInputModeFloating PinMode = 4 // Input floating mode
PinInputModePullUpDown PinMode = 8 // Input pull up/down mode pinInputModePullUpDown PinMode = 8 // Input pull up/down mode
PinInputModeReserved PinMode = 12 // Input mode (reserved) pinInputModeReserved PinMode = 12 // Input mode (reserved)
PinOutputModeGPPushPull PinMode = 0 // Output mode general purpose push/pull pinOutputModeGPPushPull PinMode = 0 // Output mode general purpose push/pull
PinOutputModeGPOpenDrain PinMode = 4 // Output mode general purpose open drain pinOutputModeGPOpenDrain PinMode = 4 // Output mode general purpose open drain
PinOutputModeAltPushPull PinMode = 8 // Output mode alt. purpose push/pull pinOutputModeAltPushPull PinMode = 8 // Output mode alt. purpose push/pull
PinOutputModeAltOpenDrain PinMode = 12 // Output mode alt. purpose open drain pinOutputModeAltOpenDrain PinMode = 12 // Output mode alt. purpose open drain
// Pull-up vs Pull down is not part of the CNF0 / CNF1 bits, but is // Pull-up vs Pull down is not part of the CNF0 / CNF1 bits, but is
// controlled by PxODR. Encoded using the 'spare' bit 5. // controlled by PxODR. Encoded using the 'spare' bit 5.
PinInputPulldown PinMode = PinInputModePullUpDown PinInputPulldown PinMode = pinInputModePullUpDown
PinInputPullup PinMode = PinInputModePullUpDown | 0x10 PinInputPullup PinMode = pinInputModePullUpDown | 0x10
) )
// Pin constants for all stm32f103 package sizes // Pin constants for all stm32f103 package sizes
@@ -166,7 +166,7 @@ func (p Pin) Configure(config PinConfig) {
// If configured for input pull-up or pull-down, set ODR // If configured for input pull-up or pull-down, set ODR
// for desired pull-up or pull-down. // for desired pull-up or pull-down.
if (config.Mode & 0xf) == PinInputModePullUpDown { if (config.Mode & 0xf) == pinInputModePullUpDown {
var pullup uint32 var pullup uint32
if config.Mode == PinInputPullup { if config.Mode == PinInputPullup {
pullup = 1 pullup = 1
@@ -290,8 +290,8 @@ func (uart *UART) configurePins(config UARTConfig) {
default: default:
// use standard TX/RX pins PA9 and PA10 // use standard TX/RX pins PA9 and PA10
} }
config.TX.Configure(PinConfig{Mode: PinOutput50MHz + PinOutputModeAltPushPull}) config.TX.Configure(PinConfig{Mode: PinOutput50MHz + pinOutputModeAltPushPull})
config.RX.Configure(PinConfig{Mode: PinInputModeFloating}) config.RX.Configure(PinConfig{Mode: pinInputModeFloating})
} }
// Determine the divisor for USARTs to get the given baudrate // Determine the divisor for USARTs to get the given baudrate
@@ -363,9 +363,9 @@ func (spi SPI) getBaudRate(config SPIConfig) uint32 {
// Configure SPI pins for input output and clock // Configure SPI pins for input output and clock
func (spi SPI) configurePins(config SPIConfig) { func (spi SPI) configurePins(config SPIConfig) {
config.SCK.Configure(PinConfig{Mode: PinOutput50MHz + PinOutputModeAltPushPull}) config.SCK.Configure(PinConfig{Mode: PinOutput50MHz + pinOutputModeAltPushPull})
config.SDO.Configure(PinConfig{Mode: PinOutput50MHz + PinOutputModeAltPushPull}) config.SDO.Configure(PinConfig{Mode: PinOutput50MHz + pinOutputModeAltPushPull})
config.SDI.Configure(PinConfig{Mode: PinInputModeFloating}) config.SDI.Configure(PinConfig{Mode: pinInputModeFloating})
} }
//---------- I2C related types and code //---------- I2C related types and code
@@ -390,8 +390,8 @@ func (i2c *I2C) configurePins(config I2CConfig) {
stm32.AFIO.MAPR.SetBits(stm32.AFIO_MAPR_I2C1_REMAP) stm32.AFIO.MAPR.SetBits(stm32.AFIO_MAPR_I2C1_REMAP)
} }
config.SDA.Configure(PinConfig{Mode: PinOutput50MHz + PinOutputModeAltOpenDrain}) config.SDA.Configure(PinConfig{Mode: PinOutput50MHz + pinOutputModeAltOpenDrain})
config.SCL.Configure(PinConfig{Mode: PinOutput50MHz + PinOutputModeAltOpenDrain}) config.SCL.Configure(PinConfig{Mode: PinOutput50MHz + pinOutputModeAltOpenDrain})
} }
func (i2c *I2C) getFreqRange(config I2CConfig) uint32 { func (i2c *I2C) getFreqRange(config I2CConfig) uint32 {
@@ -717,7 +717,7 @@ func (t *TIM) configurePin(channel uint8, pf PinFunction) {
stm32.AFIO.MAPR.ReplaceBits(remap<<stm32.AFIO_MAPR2_TIM14_REMAP_Pos, stm32.AFIO_MAPR2_TIM14_REMAP_Msk, 0) stm32.AFIO.MAPR.ReplaceBits(remap<<stm32.AFIO_MAPR2_TIM14_REMAP_Pos, stm32.AFIO_MAPR2_TIM14_REMAP_Msk, 0)
} }
pf.Pin.Configure(PinConfig{Mode: PinOutput + PinOutputModeAltPushPull}) pf.Pin.Configure(PinConfig{Mode: PinOutput + pinOutputModeAltPushPull})
} }
func (t *TIM) enableMainOutput() { func (t *TIM) enableMainOutput() {
+7 -7
View File
@@ -640,8 +640,8 @@ const (
func (uart *UART) configurePins(config UARTConfig) { func (uart *UART) configurePins(config UARTConfig) {
// enable the alternate functions on the TX and RX pins // enable the alternate functions on the TX and RX pins
config.TX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTTX}, uart.TxAltFuncSelector) config.TX.ConfigureAltFunc(PinConfig{Mode: pinModeUARTTX}, uart.TxAltFuncSelector)
config.RX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTRX}, uart.RxAltFuncSelector) config.RX.ConfigureAltFunc(PinConfig{Mode: pinModeUARTRX}, uart.RxAltFuncSelector)
} }
func (uart *UART) getBaudRateDivisor(baudRate uint32) uint32 { func (uart *UART) getBaudRateDivisor(baudRate uint32) uint32 {
@@ -674,9 +674,9 @@ func (spi SPI) config8Bits() {
} }
func (spi SPI) configurePins(config SPIConfig) { func (spi SPI) configurePins(config SPIConfig) {
config.SCK.ConfigureAltFunc(PinConfig{Mode: PinModeSPICLK}, spi.AltFuncSelector) config.SCK.ConfigureAltFunc(PinConfig{Mode: pinModeSPICLK}, spi.AltFuncSelector)
config.SDO.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDO}, spi.AltFuncSelector) config.SDO.ConfigureAltFunc(PinConfig{Mode: pinModeSPISDO}, spi.AltFuncSelector)
config.SDI.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDI}, spi.AltFuncSelector) config.SDI.ConfigureAltFunc(PinConfig{Mode: pinModeSPISDI}, spi.AltFuncSelector)
} }
func (spi SPI) getBaudRate(config SPIConfig) uint32 { func (spi SPI) getBaudRate(config SPIConfig) uint32 {
@@ -723,8 +723,8 @@ type I2C struct {
} }
func (i2c *I2C) configurePins(config I2CConfig) { func (i2c *I2C) configurePins(config I2CConfig) {
config.SCL.ConfigureAltFunc(PinConfig{Mode: PinModeI2CSCL}, i2c.AltFuncSelector) config.SCL.ConfigureAltFunc(PinConfig{Mode: pinModeI2CSCL}, i2c.AltFuncSelector)
config.SDA.ConfigureAltFunc(PinConfig{Mode: PinModeI2CSDA}, i2c.AltFuncSelector) config.SDA.ConfigureAltFunc(PinConfig{Mode: pinModeI2CSDA}, i2c.AltFuncSelector)
} }
func (i2c *I2C) getFreqRange(config I2CConfig) uint32 { func (i2c *I2C) getFreqRange(config I2CConfig) uint32 {

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