mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-07-26 14:48:40 +00:00
Compare commits
76 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 154d4a781f | |||
| b5ab114514 | |||
| 0a7e74045a | |||
| f05b378b89 | |||
| 888ca4ab0c | |||
| 903bebd071 | |||
| 848c3e55a9 | |||
| 3650c2c739 | |||
| d4e04e4e49 | |||
| e41e5106cc | |||
| ca03b8d442 | |||
| d1c4ed664e | |||
| fdaddf6917 | |||
| 50a677e9b7 | |||
| 6ad6f14a04 | |||
| 19e0f4709e | |||
| ae5b297d59 | |||
| ca1a282495 | |||
| 01f5c51b77 | |||
| ad6adfd8ff | |||
| 9815628930 | |||
| 05495c4282 | |||
| d606315515 | |||
| 60fdf81209 | |||
| 39433a3553 | |||
| 04d097f4ea | |||
| 4750635a20 | |||
| 59218cd784 | |||
| 079a789d49 | |||
| ca8e1b075a | |||
| 33024d4aa2 | |||
| 49df129ccd | |||
| 3088dcadec | |||
| 7ed7e6cb11 | |||
| 0b94e486c1 | |||
| 5ff76aacab | |||
| 3ee7599a09 | |||
| 43a66b39cc | |||
| 66b21b4c86 | |||
| a9568932be | |||
| f2fbd1dd7e | |||
| 21a9aa8102 | |||
| e1757e0347 | |||
| a05fc10699 | |||
| a685217743 | |||
| ad0c15080a | |||
| 5446c6927e | |||
| 53c83fa445 | |||
| 804dc8b1f9 | |||
| e1ceca1931 | |||
| 6620c4d2aa | |||
| ccc604d2e0 | |||
| dfab1aa717 | |||
| 75bcbbe6d8 | |||
| d599959711 | |||
| 7814964693 | |||
| 2fe4a9be71 | |||
| 163631df9e | |||
| 9ad96fd809 | |||
| 4a658b9082 | |||
| 34e0961a79 | |||
| 875d36cba0 | |||
| 1a6bed3305 | |||
| e0b9b1ecd1 | |||
| 149c9533e2 | |||
| a85df334e6 | |||
| 89a9c09af5 | |||
| 1451eeaf41 | |||
| e8c84d24a0 | |||
| a4f3457747 | |||
| aa3481e06a | |||
| 2136cb2f59 | |||
| acb3cfba6d | |||
| 8cfc4005d3 | |||
| 2dbe29327a | |||
| de0fbb5e2f |
+61
-6
@@ -93,7 +93,6 @@ commands:
|
||||
key: wasi-libc-sysroot-systemclang-v1
|
||||
paths:
|
||||
- lib/wasi-libc/sysroot
|
||||
- run: tinygo clean
|
||||
- run: go test -v -tags=llvm<<parameters.llvm>> ./cgo ./compileopts ./interp ./transform .
|
||||
- run: make gen-device -j4
|
||||
- run: make smoketest
|
||||
@@ -102,7 +101,6 @@ commands:
|
||||
key: go-cache-v2-{{ checksum "go.mod" }}-{{ .Environment.CIRCLE_BUILD_NUM }}
|
||||
paths:
|
||||
- ~/.cache/go-build
|
||||
- ~/.cache/tinygo
|
||||
- /go/pkg/mod
|
||||
- run: make fmt-check
|
||||
assert-test-linux:
|
||||
@@ -160,7 +158,6 @@ commands:
|
||||
key: go-cache-v2-{{ checksum "go.mod" }}-{{ .Environment.CIRCLE_BUILD_NUM }}
|
||||
paths:
|
||||
- ~/.cache/go-build
|
||||
- ~/.cache/tinygo
|
||||
- /go/pkg/mod
|
||||
- run: make gen-device -j4
|
||||
- run: make smoketest TINYGO=build/tinygo
|
||||
@@ -233,7 +230,6 @@ commands:
|
||||
key: go-cache-v2-{{ checksum "go.mod" }}-{{ .Environment.CIRCLE_BUILD_NUM }}
|
||||
paths:
|
||||
- ~/.cache/go-build
|
||||
- ~/.cache/tinygo
|
||||
- /go/pkg/mod
|
||||
- run:
|
||||
name: "Extract release tarball"
|
||||
@@ -317,9 +313,54 @@ commands:
|
||||
key: go-cache-macos-v2-{{ checksum "go.mod" }}-{{ .Environment.CIRCLE_BUILD_NUM }}
|
||||
paths:
|
||||
- ~/.cache/go-build
|
||||
- ~/.cache/tinygo
|
||||
- /go/pkg/mod
|
||||
|
||||
arch-release:
|
||||
steps:
|
||||
- run:
|
||||
name: Install dependencies
|
||||
command: pacman -Sy --noconfirm openssh git pacman-contrib binutils
|
||||
- run:
|
||||
name: Create TinyGo user
|
||||
command: useradd -m tinygo
|
||||
- run:
|
||||
name: Become TinyGo user
|
||||
command: su tinygo
|
||||
- run:
|
||||
name: Start SSH Agent
|
||||
command: eval $(ssh-agent -s)
|
||||
- run:
|
||||
name: Add ARCH_RELEASE_SSH_PRIVATE_KEY identity
|
||||
command: echo "${ARCH_RELEASE_SSH_PRIVATE_KEY}" | tr -d '\r' | ssh-add -
|
||||
- run:
|
||||
name: Create SSH directory
|
||||
command: mkdir -p ~/.ssh && chmod 700 ~/.ssh
|
||||
- run:
|
||||
name: Add aur.archlinux.org to known hosts
|
||||
command: ssh-keyscan aur.archlinux.org >> ~/.ssh/known_hosts
|
||||
- run:
|
||||
name: Clone tinygo-bin repo
|
||||
command: git clone ssh://aur@aur.archlinux.org/tinygo-bin.git ~/tinygo-bin
|
||||
- run:
|
||||
name: Update package version
|
||||
command: sed -i -E "s/(pkgver=)(.*)$/\1${CIRCLE_TAG}/" ~/tinygo-bin/PKGBUILD
|
||||
- run:
|
||||
name: Update file checksums
|
||||
command: cd ~/tinygo-bin && updpkgsums
|
||||
- run:
|
||||
name: Update .SRCINFO
|
||||
command: cd ~/tinygo-bin && makepkg --printsrcinfo > .SRCINFO
|
||||
# Commit the update
|
||||
- run:
|
||||
name: Set git commit config
|
||||
command: |
|
||||
git config --global user.email "tinygo-bot@tinygo.org" &&
|
||||
git config --global user.name "TinyGo Release Bot"
|
||||
- run:
|
||||
name: Commit and push changes
|
||||
command: |
|
||||
cd ~/tinygo-bin &&
|
||||
git commit -a -m "Update tinygo-bin to v${CIRCLE_TAG}" &&
|
||||
git push origin master
|
||||
|
||||
jobs:
|
||||
test-llvm9-go111:
|
||||
@@ -361,6 +402,11 @@ jobs:
|
||||
xcode: "10.1.0"
|
||||
steps:
|
||||
- build-macos
|
||||
arch-release:
|
||||
docker:
|
||||
- image: archlinux:latest
|
||||
steps:
|
||||
- arch-release
|
||||
|
||||
|
||||
|
||||
@@ -375,3 +421,12 @@ workflows:
|
||||
- build-linux
|
||||
- build-macos
|
||||
- assert-test-linux
|
||||
release:
|
||||
jobs:
|
||||
- arch-release:
|
||||
filters:
|
||||
branches:
|
||||
ignore: /.*/
|
||||
tags:
|
||||
# Runs on every semver release
|
||||
only: /v[0-9]+(\.[0-9]+)*(-.*)*/
|
||||
|
||||
@@ -5,12 +5,16 @@ src/device/avr/*.ld
|
||||
src/device/avr/*.s
|
||||
src/device/nrf/*.go
|
||||
src/device/nrf/*.s
|
||||
src/device/nxp/*.go
|
||||
src/device/nxp/*.s
|
||||
src/device/sam/*.go
|
||||
src/device/sam/*.s
|
||||
src/device/sifive/*.go
|
||||
src/device/sifive/*.s
|
||||
src/device/stm32/*.go
|
||||
src/device/stm32/*.s
|
||||
src/device/kendryte/*.go
|
||||
src/device/kendryte/*.s
|
||||
vendor
|
||||
llvm-build
|
||||
llvm-project
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@
|
||||
url = https://github.com/avr-rust/avr-mcu.git
|
||||
[submodule "lib/cmsis-svd"]
|
||||
path = lib/cmsis-svd
|
||||
url = https://github.com/posborne/cmsis-svd
|
||||
url = https://github.com/tinygo-org/cmsis-svd
|
||||
[submodule "lib/compiler-rt"]
|
||||
path = lib/compiler-rt
|
||||
url = https://github.com/llvm-mirror/compiler-rt.git
|
||||
|
||||
+12
@@ -10,6 +10,14 @@ This guide describes how to statically link TinyGo against LLVM, libclang and
|
||||
lld so that the binary can be easily moved between systems. It also shows how to
|
||||
build a release tarball that includes this binary and all necessary extra files.
|
||||
|
||||
**Note**: this documentation describes how to build a statically linked release
|
||||
tarball. If you want to develop TinyGo, you will probably want to follow a
|
||||
different guide:
|
||||
|
||||
* [Linux](https://tinygo.org/getting-started/linux/#source-install)
|
||||
* [macOS](https://tinygo.org/getting-started/macos/#source-install)
|
||||
* [Windows](https://tinygo.org/getting-started/windows/#source-install)
|
||||
|
||||
## Dependencies
|
||||
|
||||
LLVM, Clang and LLD are quite light on dependencies, requiring only standard
|
||||
@@ -84,6 +92,10 @@ Now that we have a working static build, it's time to make a release tarball:
|
||||
|
||||
make release
|
||||
|
||||
If you did not clone the repository with the `--recursive` option, you will get errors until you initialize the project submodules:
|
||||
|
||||
git submodule update --init
|
||||
|
||||
The release tarball is stored in build/release.tar.gz, and can be extracted with
|
||||
the following command (for example in ~/lib):
|
||||
|
||||
|
||||
@@ -1,3 +1,92 @@
|
||||
0.14.0
|
||||
---
|
||||
* **command-line**
|
||||
- fix `getDefaultPort()` on non-English Windows locales
|
||||
- compileopts: improve error reporting of unsupported flags
|
||||
- fix test subcommand
|
||||
- use auto-retry to locate MSD for UF2 and HEX flashing
|
||||
- fix touchSerialPortAt1200bps on Windows
|
||||
- support package names with backslashes on Windows
|
||||
* **compiler**
|
||||
- fix a few crashes due to named types
|
||||
- add support for atomic operations
|
||||
- move the channel blocked list onto the stack
|
||||
- fix -gc=none
|
||||
- fix named string to `[]byte` slice conversion
|
||||
- implement func value and builtin defers
|
||||
- add proper parameter names to runtime.initAll, to fix a panic
|
||||
- builder: fix picolibc include path
|
||||
- builder: use newer version of gohex
|
||||
- builder: try to determine stack size information at compile time
|
||||
- builder: remove -opt=0
|
||||
- interp: fix sync/atomic.Value load/store methods
|
||||
- loader: add Go module support
|
||||
- transform: fix debug information in func lowering pass
|
||||
- transform: do not special-case zero or one implementations of a method call
|
||||
- transform: introduce check for method calls on nil interfaces
|
||||
- transform: gc: track 0-index GEPs to fix miscompilation
|
||||
* **cgo**
|
||||
- Add LDFlags support
|
||||
* **standard library**
|
||||
- extend stdlib to allow import of more packages
|
||||
- replace master/slave terminology with appropriate alternatives (MOSI->SDO
|
||||
etc)
|
||||
- `internal/bytealg`: reimplement bytealg in pure Go
|
||||
- `internal/task`: fix nil panic in (*internal/task.Stack).Pop
|
||||
- `os`: add Args and stub it with mock data
|
||||
- `os`: implement virtual filesystem support
|
||||
- `reflect`: add Cap and Len support for map and chan
|
||||
- `runtime`: fix return address in scheduler on RISC-V
|
||||
- `runtime`: avoid recursion in printuint64 function
|
||||
- `runtime`: replace ReadRegister with AsmFull inline assembly
|
||||
- `runtime`: fix compilation errors when using gc.extalloc
|
||||
- `runtime`: add cap and len support for chans
|
||||
- `runtime`: refactor time handling (improving accuracy)
|
||||
- `runtime`: make channels work in interrupts
|
||||
- `runtime/interrupt`: add cross-chip disable/restore interrupt support
|
||||
- `sync`: implement `sync.Cond`
|
||||
- `sync`: add WaitGroup
|
||||
* **targets**
|
||||
- `arm`: allow nesting in DisableInterrupts and EnableInterrupts
|
||||
- `arm`: make FPU configuraton consistent
|
||||
- `arm`: do not mask fault handlers in critical sections
|
||||
- `atmega2560`: fix pin mapping for pins D2, D5 and the L port
|
||||
- `atsamd`: return an error when an incorrect PWM pin is used
|
||||
- `atsamd`: add support for pin change interrupts
|
||||
- `atsamd`: add DAC support
|
||||
- `atsamd21`: add more ADC pins
|
||||
- `atsamd51`: fix ROM / RAM size on atsamd51j20
|
||||
- `atsamd51`: add more pins
|
||||
- `atsamd51`: add more ADC pins
|
||||
- `atsamd51`: add pin change interrupt settings
|
||||
- `atsamd51`: extend pinPadMapping
|
||||
- `arduino-nano33`: use (U)SB flag to ensure that device can be found when
|
||||
not on default port
|
||||
- `arduino-nano33`: remove (d)ebug flag to reduce console noise when flashing
|
||||
- `avr`: use standard pin numbering
|
||||
- `avr`: unify GPIO pin/port code
|
||||
- `avr`: add support for PinInputPullup
|
||||
- `avr`: work around codegen bug in LLVM 10
|
||||
- `avr`: fix target triple
|
||||
- `fe310`: remove extra println left in by mistake
|
||||
- `feather-nrf52840`: add support for the Feather nRF52840
|
||||
- `maixbit`: add board definition and dummy runtime
|
||||
- `nintendoswitch`: Add experimental Nintendo Switch support without CRT
|
||||
- `nrf`: expose the RAM base address
|
||||
- `nrf`: add support for pin change interrupts
|
||||
- `nrf`: add microbit-s110v8 target
|
||||
- `nrf`: fix bug in SPI.Tx
|
||||
- `nrf`: support debugging the PCA10056
|
||||
- `pygamer`: add Adafruit PyGamer suport
|
||||
- `riscv`: fix interrupt configuration bug
|
||||
- `riscv`: disable linker relaxations during gp init
|
||||
- `stm32f4disco`: add new target with ST-Link v2.1 debugger
|
||||
- `teensy36`: add Teensy 3.6 support
|
||||
- `wasm`: fix event handling
|
||||
- `wasm`: add --no-demangle linker option
|
||||
- `wioterminal`: add support for the Seeed Wio Terminal
|
||||
- `xiao`: add support for the Seeed XIAO
|
||||
|
||||
0.13.1
|
||||
---
|
||||
* **standard library**
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ Microcontrollers have lots of peripherals (I2C, SPI, ADC, etc.) and many don't h
|
||||
|
||||
## How to use our Github repository
|
||||
|
||||
The `master` branch of this repo will always have the latest released version of TinyGo. All of the active development work for the next release will take place in the `dev` branch. TinyGo will use semantic versioning and will create a tag/release for each release.
|
||||
The `release` branch of this repo will always have the latest released version of TinyGo. All of the active development work for the next release will take place in the `dev` branch. TinyGo will use semantic versioning and will create a tag/release for each release.
|
||||
|
||||
Here is how to contribute back some code or documentation:
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ else
|
||||
LLVM_OPTION += '-DLLVM_ENABLE_ASSERTIONS=OFF'
|
||||
endif
|
||||
|
||||
.PHONY: all tinygo test $(LLVM_BUILDDIR) llvm-source clean fmt gen-device gen-device-nrf gen-device-avr
|
||||
.PHONY: all tinygo test $(LLVM_BUILDDIR) llvm-source clean fmt gen-device gen-device-nrf gen-device-nxp gen-device-avr
|
||||
|
||||
LLVM_COMPONENTS = all-targets analysis asmparser asmprinter bitreader bitwriter codegen core coroutines coverage debuginfodwarf executionengine frontendopenmp instrumentation interpreter ipo irreader linker lto mc mcjit objcarcopts option profiledata scalaropts support target
|
||||
|
||||
@@ -118,7 +118,7 @@ fmt-check:
|
||||
@unformatted=$$(gofmt -l $(FMT_PATHS)); [ -z "$$unformatted" ] && exit 0; echo "Unformatted:"; for fn in $$unformatted; do echo " $$fn"; done; exit 1
|
||||
|
||||
|
||||
gen-device: gen-device-avr gen-device-nrf gen-device-sam gen-device-sifive gen-device-stm32
|
||||
gen-device: gen-device-avr gen-device-nrf gen-device-sam gen-device-sifive gen-device-stm32 gen-device-kendryte gen-device-nxp
|
||||
|
||||
gen-device-avr:
|
||||
$(GO) build -o ./build/gen-device-avr ./tools/gen-device-avr/
|
||||
@@ -133,6 +133,10 @@ gen-device-nrf: build/gen-device-svd
|
||||
./build/gen-device-svd -source=https://github.com/NordicSemiconductor/nrfx/tree/master/mdk lib/nrfx/mdk/ src/device/nrf/
|
||||
GO111MODULE=off $(GO) fmt ./src/device/nrf
|
||||
|
||||
gen-device-nxp: build/gen-device-svd
|
||||
./build/gen-device-svd -source=https://github.com/posborne/cmsis-svd/tree/master/data/NXP lib/cmsis-svd/data/NXP/ src/device/nxp/
|
||||
GO111MODULE=off $(GO) fmt ./src/device/nxp
|
||||
|
||||
gen-device-sam: build/gen-device-svd
|
||||
./build/gen-device-svd -source=https://github.com/posborne/cmsis-svd/tree/master/data/Atmel lib/cmsis-svd/data/Atmel/ src/device/sam/
|
||||
GO111MODULE=off $(GO) fmt ./src/device/sam
|
||||
@@ -141,6 +145,10 @@ gen-device-sifive: build/gen-device-svd
|
||||
./build/gen-device-svd -source=https://github.com/posborne/cmsis-svd/tree/master/data/SiFive-Community -interrupts=software lib/cmsis-svd/data/SiFive-Community/ src/device/sifive/
|
||||
GO111MODULE=off $(GO) fmt ./src/device/sifive
|
||||
|
||||
gen-device-kendryte: build/gen-device-svd
|
||||
./build/gen-device-svd -source=https://github.com/posborne/cmsis-svd/tree/master/data/Kendryte-Community -interrupts=software lib/cmsis-svd/data/Kendryte-Community/ src/device/kendryte/
|
||||
GO111MODULE=off $(GO) fmt ./src/device/kendryte
|
||||
|
||||
gen-device-stm32: build/gen-device-svd
|
||||
./build/gen-device-svd -source=https://github.com/posborne/cmsis-svd/tree/master/data/STMicro lib/cmsis-svd/data/STMicro/ src/device/stm32/
|
||||
GO111MODULE=off $(GO) fmt ./src/device/stm32
|
||||
@@ -148,13 +156,13 @@ gen-device-stm32: build/gen-device-svd
|
||||
|
||||
# Get LLVM sources.
|
||||
$(LLVM_PROJECTDIR)/README.md:
|
||||
git clone -b release/10.x https://github.com/llvm/llvm-project $(LLVM_PROJECTDIR)
|
||||
git clone -b release/10.x --depth=1 https://github.com/llvm/llvm-project $(LLVM_PROJECTDIR)
|
||||
llvm-source: $(LLVM_PROJECTDIR)/README.md
|
||||
|
||||
# Configure LLVM.
|
||||
TINYGO_SOURCE_DIR=$(shell pwd)
|
||||
$(LLVM_BUILDDIR)/build.ninja: llvm-source
|
||||
mkdir -p $(LLVM_BUILDDIR); cd $(LLVM_BUILDDIR); cmake -G Ninja $(TINYGO_SOURCE_DIR)/$(LLVM_PROJECTDIR)/llvm "-DLLVM_TARGETS_TO_BUILD=X86;ARM;AArch64;RISCV;WebAssembly" "-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=AVR" -DCMAKE_BUILD_TYPE=Release -DLIBCLANG_BUILD_STATIC=ON -DLLVM_ENABLE_TERMINFO=OFF -DLLVM_ENABLE_ZLIB=OFF -DLLVM_ENABLE_PROJECTS="clang;lld" -DLLVM_TOOL_CLANG_TOOLS_EXTRA_BUILD=OFF $(LLVM_OPTION)
|
||||
mkdir -p $(LLVM_BUILDDIR); cd $(LLVM_BUILDDIR); cmake -G Ninja $(TINYGO_SOURCE_DIR)/$(LLVM_PROJECTDIR)/llvm "-DLLVM_TARGETS_TO_BUILD=X86;ARM;AArch64;RISCV;WebAssembly" "-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=AVR" -DCMAKE_BUILD_TYPE=Release -DLIBCLANG_BUILD_STATIC=ON -DLLVM_ENABLE_TERMINFO=OFF -DLLVM_ENABLE_ZLIB=OFF -DLLVM_ENABLE_LIBEDIT=OFF -DLLVM_ENABLE_Z3_SOLVER=OFF -DLLVM_ENABLE_OCAMLDOC=OFF -DLLVM_ENABLE_PROJECTS="clang;lld" -DLLVM_TOOL_CLANG_TOOLS_EXTRA_BUILD=OFF $(LLVM_OPTION)
|
||||
|
||||
# Build LLVM.
|
||||
$(LLVM_BUILDDIR): $(LLVM_BUILDDIR)/build.ninja
|
||||
@@ -259,6 +267,8 @@ smoketest:
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=stm32f4disco examples/blinky2
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=stm32f4disco-1 examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=circuitplay-bluefruit examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=circuitplay-express examples/i2s
|
||||
@@ -296,8 +306,15 @@ smoketest:
|
||||
$(TINYGO) build -size short -o test.hex -target=wioterminal examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=pygamer examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=xiao examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=circuitplay-express examples/dac
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=pyportal examples/dac
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=feather-nrf52840 examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
ifneq ($(AVR), 0)
|
||||
$(TINYGO) build -size short -o test.hex -target=atmega1284p examples/serial
|
||||
@$(MD5SUM) test.hex
|
||||
@@ -316,8 +333,17 @@ ifneq ($(AVR), 0)
|
||||
endif
|
||||
$(TINYGO) build -size short -o test.hex -target=hifive1b examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=maixbit examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -o wasm.wasm -target=wasm examples/wasm/export
|
||||
$(TINYGO) build -o wasm.wasm -target=wasm examples/wasm/main
|
||||
# test various compiler flags
|
||||
$(TINYGO) build -size short -o test.hex -target=pca10040 -gc=none -scheduler=none examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=pca10040 -opt=1 examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -o test.elf -target=nintendoswitch examples/serial
|
||||
@$(MD5SUM) test.elf
|
||||
|
||||
wasmtest:
|
||||
$(GO) test ./tests/wasm
|
||||
|
||||
@@ -43,17 +43,19 @@ See the [getting started instructions](https://tinygo.org/getting-started/) for
|
||||
|
||||
You can compile TinyGo programs for microcontrollers, WebAssembly and Linux.
|
||||
|
||||
The following 34 microcontroller boards are currently supported:
|
||||
The following 39 microcontroller boards/devices are currently supported:
|
||||
|
||||
* [Adafruit Circuit Playground Bluefruit](https://www.adafruit.com/product/4333)
|
||||
* [Adafruit Circuit Playground Express](https://www.adafruit.com/product/3333)
|
||||
* [Adafruit CLUE Alpha](https://www.adafruit.com/product/4500)
|
||||
* [Adafruit Feather M0](https://www.adafruit.com/product/2772)
|
||||
* [Adafruit Feather M4](https://www.adafruit.com/product/3857)
|
||||
* [Adafruit Feather nRF52840 Express](https://www.adafruit.com/product/4062)
|
||||
* [Adafruit ItsyBitsy M0](https://www.adafruit.com/product/3727)
|
||||
* [Adafruit ItsyBitsy M4](https://www.adafruit.com/product/3800)
|
||||
* [Adafruit Metro M4 Express Airlift](https://www.adafruit.com/product/4000)
|
||||
* [Adafruit PyBadge](https://www.adafruit.com/product/4200)
|
||||
* [Adafruit PyGamer](https://www.adafruit.com/product/4242)
|
||||
* [Adafruit PyPortal](https://www.adafruit.com/product/4116)
|
||||
* [Adafruit Trinket M0](https://www.adafruit.com/product/3500)
|
||||
* [Arduino Mega 2560](https://store.arduino.cc/arduino-mega-2560-rev3)
|
||||
@@ -64,6 +66,7 @@ The following 34 microcontroller boards are currently supported:
|
||||
* [Digispark](http://digistump.com/products/1)
|
||||
* [Game Boy Advance](https://en.wikipedia.org/wiki/Game_Boy_Advance)
|
||||
* [Makerdiary nRF52840-MDK](https://wiki.makerdiary.com/nrf52840-mdk/)
|
||||
* [Nintendo Switch](https://www.nintendo.com/switch/)
|
||||
* [Nordic Semiconductor PCA10031](https://www.nordicsemi.com/eng/Products/nRF51-Dongle)
|
||||
* [Nordic Semiconductor PCA10040](https://www.nordicsemi.com/eng/Products/Bluetooth-low-energy/nRF52-DK)
|
||||
* [Nordic Semiconductor PCA10056](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-DK)
|
||||
@@ -72,8 +75,10 @@ The following 34 microcontroller boards are currently supported:
|
||||
* [Particle Xenon](https://docs.particle.io/datasheets/discontinued/xenon-datasheet/)
|
||||
* [Phytec reel board](https://www.phytec.eu/product-eu/internet-of-things/reelboard/)
|
||||
* [PineTime DevKit](https://www.pine64.org/pinetime/)
|
||||
* [PJRC Teensy 3.6](https://www.pjrc.com/store/teensy36.html)
|
||||
* [Seeed Wio Terminal](https://www.seeedstudio.com/Wio-Terminal-p-4509.html)
|
||||
* [Seeed Seeeduino XIAO](https://www.seeedstudio.com/Seeeduino-XIAO-Arduino-Microcontroller-SAMD21-Cortex-M0+-p-4426.html)
|
||||
* [Seeed Sipeed MAix BiT](https://www.seeedstudio.com/Sipeed-MAix-BiT-for-RISC-V-AI-IoT-p-2872.html)
|
||||
* [SiFIve HiFive1](https://www.sifive.com/boards/hifive1)
|
||||
* [ST Micro "Nucleo F103RB"](https://www.st.com/en/evaluation-tools/nucleo-f103rb.html)
|
||||
* [ST Micro STM32F103XX "Bluepill"](http://wiki.stm32duino.com/index.php?title=Blue_Pill)
|
||||
@@ -139,3 +144,5 @@ The original reasoning was: if [Python](https://micropython.org/) can run on mic
|
||||
This project is licensed under the BSD 3-clause license, just like the [Go project](https://golang.org/LICENSE) itself.
|
||||
|
||||
Some code has been copied from the LLVM project and is therefore licensed under [a variant of the Apache 2.0 license](http://releases.llvm.org/10.0.0/LICENSE.TXT). This has been clearly indicated in the header of these files.
|
||||
|
||||
Some code has been copied and/or ported from Paul Stoffregen's Teensy libraries and is therefore licensed under PJRC's license. This has been clearly indicated in the header of these files.
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
# Avoid lengthy LLVM rebuilds on each newly pushed branch. Pull requests will
|
||||
# be built anyway.
|
||||
trigger:
|
||||
- master
|
||||
- release
|
||||
- dev
|
||||
|
||||
jobs:
|
||||
@@ -43,7 +43,7 @@ jobs:
|
||||
displayName: Install QEMU
|
||||
inputs:
|
||||
targetType: inline
|
||||
script: choco install qemu
|
||||
script: choco install qemu --version=2020.06.12
|
||||
- task: CacheBeta@0
|
||||
displayName: Cache wasi-libc sysroot
|
||||
inputs:
|
||||
|
||||
+103
-2
@@ -4,11 +4,13 @@
|
||||
package builder
|
||||
|
||||
import (
|
||||
"debug/elf"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@@ -16,6 +18,7 @@ import (
|
||||
"github.com/tinygo-org/tinygo/compiler"
|
||||
"github.com/tinygo-org/tinygo/goenv"
|
||||
"github.com/tinygo-org/tinygo/interp"
|
||||
"github.com/tinygo-org/tinygo/stacksize"
|
||||
"github.com/tinygo-org/tinygo/transform"
|
||||
"tinygo.org/x/go-llvm"
|
||||
)
|
||||
@@ -73,8 +76,15 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(stri
|
||||
// exactly.
|
||||
errs = nil
|
||||
switch config.Options.Opt {
|
||||
case "none", "0":
|
||||
errs = transform.Optimize(mod, config, 0, 0, 0) // -O0
|
||||
/*
|
||||
Currently, turning optimizations off causes compile failures.
|
||||
We rely on the optimizer removing some dead symbols.
|
||||
Avoid providing an option that does not work right now.
|
||||
In the future once everything has been fixed we can re-enable this.
|
||||
|
||||
case "none", "0":
|
||||
errs = transform.Optimize(mod, config, 0, 0, 0) // -O0
|
||||
*/
|
||||
case "1":
|
||||
errs = transform.Optimize(mod, config, 1, 0, 0) // -O1
|
||||
case "2":
|
||||
@@ -216,6 +226,11 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(stri
|
||||
}
|
||||
}
|
||||
|
||||
// Print goroutine stack sizes, as far as possible.
|
||||
if config.Options.PrintStacks {
|
||||
printStacks(mod, executable)
|
||||
}
|
||||
|
||||
// Get an Intel .hex file or .bin file from the .elf file.
|
||||
if outext == ".hex" || outext == ".bin" || outext == ".gba" {
|
||||
tmppath = filepath.Join(dir, "main"+outext)
|
||||
@@ -234,3 +249,89 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(stri
|
||||
return action(tmppath)
|
||||
}
|
||||
}
|
||||
|
||||
// printStacks prints the maximum stack depth for functions that are started as
|
||||
// goroutines. Stack sizes cannot always be determined statically, in particular
|
||||
// recursive functions and functions that call interface methods or function
|
||||
// pointers may have an unknown stack depth (depending on what the optimizer
|
||||
// manages to optimize away).
|
||||
//
|
||||
// It might print something like the following:
|
||||
//
|
||||
// function stack usage (in bytes)
|
||||
// Reset_Handler 316
|
||||
// .Lexamples/blinky2.led1 92
|
||||
// .Lruntime.run$1 300
|
||||
func printStacks(mod llvm.Module, executable string) {
|
||||
// Determine which functions call a function pointer.
|
||||
var callsIndirectFunction []string
|
||||
for fn := mod.FirstFunction(); !fn.IsNil(); fn = llvm.NextFunction(fn) {
|
||||
for bb := fn.FirstBasicBlock(); !bb.IsNil(); bb = llvm.NextBasicBlock(bb) {
|
||||
for inst := bb.FirstInstruction(); !inst.IsNil(); inst = llvm.NextInstruction(inst) {
|
||||
if inst.IsACallInst().IsNil() {
|
||||
continue
|
||||
}
|
||||
if callee := inst.CalledValue(); callee.IsAFunction().IsNil() && callee.IsAInlineAsm().IsNil() {
|
||||
callsIndirectFunction = append(callsIndirectFunction, fn.Name())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Load the ELF binary.
|
||||
f, err := elf.Open(executable)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, "could not load executable for stack size analysis:", err)
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
// Determine the frame size of each function (if available) and the callgraph.
|
||||
functions, err := stacksize.CallGraph(f, callsIndirectFunction)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, "could not parse executable for stack size analysis:", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Get a list of "go wrappers", small wrapper functions that decode
|
||||
// parameters when starting a new goroutine.
|
||||
var gowrappers []string
|
||||
for name := range functions {
|
||||
if strings.HasSuffix(name, "$gowrapper") {
|
||||
gowrappers = append(gowrappers, name)
|
||||
}
|
||||
}
|
||||
sort.Strings(gowrappers)
|
||||
|
||||
switch f.Machine {
|
||||
case elf.EM_ARM:
|
||||
// Add the reset handler, which runs startup code and is the
|
||||
// interrupt/scheduler stack with -scheduler=tasks.
|
||||
// Note that because interrupts happen on this stack, the stack needed
|
||||
// by just the Reset_Handler is not enough. Stacks needed by interrupt
|
||||
// handlers should also be taken into account.
|
||||
gowrappers = append([]string{"Reset_Handler"}, gowrappers...)
|
||||
}
|
||||
|
||||
// Print the sizes of all stacks.
|
||||
fmt.Printf("%-32s %s\n", "function", "stack usage (in bytes)")
|
||||
for _, name := range gowrappers {
|
||||
for _, fn := range functions[name] {
|
||||
stackSize, stackSizeType, missingStackSize := fn.StackSize()
|
||||
strippedName := name
|
||||
if strings.HasSuffix(name, "$gowrapper") {
|
||||
strippedName = name[:len(name)-len("$gowrapper")]
|
||||
}
|
||||
switch stackSizeType {
|
||||
case stacksize.Bounded:
|
||||
fmt.Printf("%-32s %d\n", strippedName, stackSize)
|
||||
case stacksize.Unknown:
|
||||
fmt.Printf("%-32s unknown, %s does not have stack frame information\n", strippedName, missingStackSize)
|
||||
case stacksize.Recursive:
|
||||
fmt.Printf("%-32s recursive, %s may call itself\n", strippedName, missingStackSize)
|
||||
case stacksize.IndirectCall:
|
||||
fmt.Printf("%-32s unknown, %s calls a function pointer\n", strippedName, missingStackSize)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +74,9 @@ func (l *Library) Load(target string) (path string, err error) {
|
||||
if strings.HasPrefix(target, "riscv32-") {
|
||||
args = append(args, "-march=rv32imac", "-mabi=ilp32", "-fforce-enable-int128")
|
||||
}
|
||||
if strings.HasPrefix(target, "riscv64-") {
|
||||
args = append(args, "-march=rv64gc", "-mabi=lp64")
|
||||
}
|
||||
|
||||
// Compile all sources.
|
||||
var objs []string
|
||||
|
||||
@@ -176,6 +176,9 @@ func (c *Config) CFlags() []string {
|
||||
cflags = append(cflags, "-nostdlibinc", "-Xclang", "-internal-isystem", "-Xclang", filepath.Join(root, "lib", "picolibc", "newlib", "libc", "include"))
|
||||
cflags = append(cflags, "-I"+filepath.Join(root, "lib/picolibc-include"))
|
||||
}
|
||||
if c.Debug() {
|
||||
cflags = append(cflags, "-g")
|
||||
}
|
||||
return cflags
|
||||
}
|
||||
|
||||
@@ -281,6 +284,16 @@ func (c *Config) CodeModel() string {
|
||||
return "default"
|
||||
}
|
||||
|
||||
// RelocationModel returns the relocation model in use on this platform. Valid
|
||||
// values are "static", "pic", "dynamicnopic".
|
||||
func (c *Config) RelocationModel() string {
|
||||
if c.Target.RelocationModel != "" {
|
||||
return c.Target.RelocationModel
|
||||
}
|
||||
|
||||
return "static"
|
||||
}
|
||||
|
||||
type TestConfig struct {
|
||||
CompileTestBinary bool
|
||||
// TODO: Filter the test functions to run, include verbose flag, etc
|
||||
|
||||
@@ -25,6 +25,7 @@ type Options struct {
|
||||
VerifyIR bool
|
||||
Debug bool
|
||||
PrintSizes string
|
||||
PrintStacks bool
|
||||
CFlags []string
|
||||
LDFlags []string
|
||||
Tags string
|
||||
|
||||
@@ -50,6 +50,7 @@ type TargetSpec struct {
|
||||
OpenOCDTransport string `json:"openocd-transport"`
|
||||
JLinkDevice string `json:"jlink-device"`
|
||||
CodeModel string `json:"code-model"`
|
||||
RelocationModel string `json:"relocation-model"`
|
||||
}
|
||||
|
||||
// copyProperties copies all properties that are set in spec2 into itself.
|
||||
@@ -134,6 +135,10 @@ func (spec *TargetSpec) copyProperties(spec2 *TargetSpec) {
|
||||
if spec2.CodeModel != "" {
|
||||
spec.CodeModel = spec2.CodeModel
|
||||
}
|
||||
|
||||
if spec2.RelocationModel != "" {
|
||||
spec.RelocationModel = spec2.RelocationModel
|
||||
}
|
||||
}
|
||||
|
||||
// load reads a target specification from the JSON in the given io.Reader. It
|
||||
|
||||
+21
-2
@@ -74,7 +74,14 @@ type builder struct {
|
||||
deferFuncs map[*ir.Function]int
|
||||
deferInvokeFuncs map[string]int
|
||||
deferClosureFuncs map[*ir.Function]int
|
||||
deferExprFuncs map[ssa.Value]int
|
||||
selectRecvBuf map[*ssa.Select]llvm.Value
|
||||
deferBuiltinFuncs map[ssa.Value]deferBuiltin
|
||||
}
|
||||
|
||||
type deferBuiltin struct {
|
||||
funcName string
|
||||
callback int
|
||||
}
|
||||
|
||||
type phiNode struct {
|
||||
@@ -93,6 +100,7 @@ func NewTargetMachine(config *compileopts.Config) (llvm.TargetMachine, error) {
|
||||
features := strings.Join(config.Features(), ",")
|
||||
|
||||
var codeModel llvm.CodeModel
|
||||
var relocationModel llvm.RelocMode
|
||||
|
||||
switch config.CodeModel() {
|
||||
case "default":
|
||||
@@ -109,7 +117,16 @@ func NewTargetMachine(config *compileopts.Config) (llvm.TargetMachine, error) {
|
||||
codeModel = llvm.CodeModelLarge
|
||||
}
|
||||
|
||||
machine := target.CreateTargetMachine(config.Triple(), config.CPU(), features, llvm.CodeGenLevelDefault, llvm.RelocStatic, codeModel)
|
||||
switch config.RelocationModel() {
|
||||
case "static":
|
||||
relocationModel = llvm.RelocStatic
|
||||
case "pic":
|
||||
relocationModel = llvm.RelocPIC
|
||||
case "dynamicnopic":
|
||||
relocationModel = llvm.RelocDynamicNoPic
|
||||
}
|
||||
|
||||
machine := target.CreateTargetMachine(config.Triple(), config.CPU(), features, llvm.CodeGenLevelDefault, relocationModel, codeModel)
|
||||
return machine, nil
|
||||
}
|
||||
|
||||
@@ -276,6 +293,8 @@ func Compile(pkgName string, machine llvm.TargetMachine, config *compileopts.Con
|
||||
pos := c.ir.Program.Fset.Position(initFn.Pos())
|
||||
irbuilder.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), difunc, llvm.Metadata{})
|
||||
}
|
||||
initFn.LLVMFn.Param(0).SetName("context")
|
||||
initFn.LLVMFn.Param(1).SetName("parentHandle")
|
||||
block := c.ctx.AddBasicBlock(initFn.LLVMFn, "entry")
|
||||
irbuilder.SetInsertPointAtEnd(block)
|
||||
for _, fn := range initFuncs {
|
||||
@@ -2536,7 +2555,7 @@ func (b *builder) createConvert(typeFrom, typeTo types.Type, value llvm.Value, p
|
||||
return llvm.Value{}, b.makeError(pos, "todo: convert: basic non-integer type: "+typeFrom.String()+" -> "+typeTo.String())
|
||||
|
||||
case *types.Slice:
|
||||
if basic, ok := typeFrom.(*types.Basic); !ok || basic.Info()&types.IsString == 0 {
|
||||
if basic, ok := typeFrom.Underlying().(*types.Basic); !ok || basic.Info()&types.IsString == 0 {
|
||||
panic("can only convert from a string to a slice")
|
||||
}
|
||||
|
||||
|
||||
+109
-14
@@ -16,6 +16,7 @@ package compiler
|
||||
import (
|
||||
"github.com/tinygo-org/tinygo/compiler/llvmutil"
|
||||
"github.com/tinygo-org/tinygo/ir"
|
||||
"go/types"
|
||||
"golang.org/x/tools/go/ssa"
|
||||
"tinygo.org/x/go-llvm"
|
||||
)
|
||||
@@ -28,6 +29,8 @@ func (b *builder) deferInitFunc() {
|
||||
b.deferFuncs = make(map[*ir.Function]int)
|
||||
b.deferInvokeFuncs = make(map[string]int)
|
||||
b.deferClosureFuncs = make(map[*ir.Function]int)
|
||||
b.deferExprFuncs = make(map[ssa.Value]int)
|
||||
b.deferBuiltinFuncs = make(map[ssa.Value]deferBuiltin)
|
||||
|
||||
// Create defer list pointer.
|
||||
deferType := llvm.PointerType(b.getLLVMRuntimeType("_defer"), 0)
|
||||
@@ -151,9 +154,54 @@ func (b *builder) createDefer(instr *ssa.Defer) {
|
||||
values = append(values, context)
|
||||
valueTypes = append(valueTypes, context.Type())
|
||||
|
||||
} else if builtin, ok := instr.Call.Value.(*ssa.Builtin); ok {
|
||||
var funcName string
|
||||
switch builtin.Name() {
|
||||
case "close":
|
||||
funcName = "chanClose"
|
||||
default:
|
||||
b.addError(instr.Pos(), "todo: Implement defer for "+builtin.Name())
|
||||
return
|
||||
}
|
||||
|
||||
if _, ok := b.deferBuiltinFuncs[instr.Call.Value]; !ok {
|
||||
b.deferBuiltinFuncs[instr.Call.Value] = deferBuiltin{
|
||||
funcName,
|
||||
len(b.allDeferFuncs),
|
||||
}
|
||||
b.allDeferFuncs = append(b.allDeferFuncs, instr.Call.Value)
|
||||
}
|
||||
callback := llvm.ConstInt(b.uintptrType, uint64(b.deferBuiltinFuncs[instr.Call.Value].callback), false)
|
||||
|
||||
// Collect all values to be put in the struct (starting with
|
||||
// runtime._defer fields).
|
||||
values = []llvm.Value{callback, next}
|
||||
for _, param := range instr.Call.Args {
|
||||
llvmParam := b.getValue(param)
|
||||
values = append(values, llvmParam)
|
||||
valueTypes = append(valueTypes, llvmParam.Type())
|
||||
}
|
||||
|
||||
} else {
|
||||
b.addError(instr.Pos(), "todo: defer on uncommon function call type")
|
||||
return
|
||||
funcValue := b.getValue(instr.Call.Value)
|
||||
|
||||
if _, ok := b.deferExprFuncs[instr.Call.Value]; !ok {
|
||||
b.deferExprFuncs[instr.Call.Value] = len(b.allDeferFuncs)
|
||||
b.allDeferFuncs = append(b.allDeferFuncs, &instr.Call)
|
||||
}
|
||||
|
||||
callback := llvm.ConstInt(b.uintptrType, uint64(b.deferExprFuncs[instr.Call.Value]), false)
|
||||
|
||||
// Collect all values to be put in the struct (starting with
|
||||
// runtime._defer fields, followed by all parameters including the
|
||||
// context pointer).
|
||||
values = []llvm.Value{callback, next, funcValue}
|
||||
valueTypes = append(valueTypes, funcValue.Type())
|
||||
for _, param := range instr.Call.Args {
|
||||
llvmParam := b.getValue(param)
|
||||
values = append(values, llvmParam)
|
||||
valueTypes = append(valueTypes, llvmParam.Type())
|
||||
}
|
||||
}
|
||||
|
||||
// Make a struct out of the collected values to put in the defer frame.
|
||||
@@ -243,16 +291,23 @@ func (b *builder) createRunDefers() {
|
||||
b.SetInsertPointAtEnd(block)
|
||||
switch callback := callback.(type) {
|
||||
case *ssa.CallCommon:
|
||||
// Call on an interface value.
|
||||
if !callback.IsInvoke() {
|
||||
panic("expected an invoke call, not a direct call")
|
||||
}
|
||||
// Call on an value or interface value.
|
||||
|
||||
// Get the real defer struct type and cast to it.
|
||||
valueTypes := []llvm.Type{b.uintptrType, llvm.PointerType(b.getLLVMRuntimeType("_defer"), 0), b.uintptrType, b.i8ptrType}
|
||||
valueTypes := []llvm.Type{b.uintptrType, llvm.PointerType(b.getLLVMRuntimeType("_defer"), 0)}
|
||||
|
||||
if !callback.IsInvoke() {
|
||||
//Expect funcValue to be passed through the defer frame.
|
||||
valueTypes = append(valueTypes, b.getFuncType(callback.Signature()))
|
||||
} else {
|
||||
//Expect typecode
|
||||
valueTypes = append(valueTypes, b.uintptrType, b.i8ptrType)
|
||||
}
|
||||
|
||||
for _, arg := range callback.Args {
|
||||
valueTypes = append(valueTypes, b.getLLVMType(arg.Type()))
|
||||
}
|
||||
|
||||
deferFrameType := b.ctx.StructType(valueTypes, false)
|
||||
deferFramePtr := b.CreateBitCast(deferData, llvm.PointerType(deferFrameType, 0), "deferFrame")
|
||||
|
||||
@@ -265,18 +320,34 @@ func (b *builder) createRunDefers() {
|
||||
forwardParams = append(forwardParams, forwardParam)
|
||||
}
|
||||
|
||||
// Isolate the typecode.
|
||||
typecode, forwardParams := forwardParams[0], forwardParams[1:]
|
||||
var fnPtr llvm.Value
|
||||
|
||||
// Add the context parameter. An interface call cannot also be a
|
||||
// closure but we have to supply the parameter anyway for platforms
|
||||
// with a strict calling convention.
|
||||
forwardParams = append(forwardParams, llvm.Undef(b.i8ptrType))
|
||||
if !callback.IsInvoke() {
|
||||
// Isolate the func value.
|
||||
funcValue := forwardParams[0]
|
||||
forwardParams = forwardParams[1:]
|
||||
|
||||
//Get function pointer and context
|
||||
fp, context := b.decodeFuncValue(funcValue, callback.Signature())
|
||||
fnPtr = fp
|
||||
|
||||
//Pass context
|
||||
forwardParams = append(forwardParams, context)
|
||||
} else {
|
||||
// Isolate the typecode.
|
||||
typecode := forwardParams[0]
|
||||
forwardParams = forwardParams[1:]
|
||||
fnPtr = b.getInvokePtr(callback, typecode)
|
||||
|
||||
// Add the context parameter. An interface call cannot also be a
|
||||
// closure but we have to supply the parameter anyway for platforms
|
||||
// with a strict calling convention.
|
||||
forwardParams = append(forwardParams, llvm.Undef(b.i8ptrType))
|
||||
}
|
||||
|
||||
// Parent coroutine handle.
|
||||
forwardParams = append(forwardParams, llvm.Undef(b.i8ptrType))
|
||||
|
||||
fnPtr := b.getInvokePtr(callback, typecode)
|
||||
b.createCall(fnPtr, forwardParams, "")
|
||||
|
||||
case *ir.Function:
|
||||
@@ -339,7 +410,31 @@ func (b *builder) createRunDefers() {
|
||||
|
||||
// Call deferred function.
|
||||
b.createCall(fn.LLVMFn, forwardParams, "")
|
||||
case *ssa.Builtin:
|
||||
db := b.deferBuiltinFuncs[callback]
|
||||
|
||||
//Get parameter types
|
||||
valueTypes := []llvm.Type{b.uintptrType, llvm.PointerType(b.getLLVMRuntimeType("_defer"), 0)}
|
||||
|
||||
//Get signature from call results
|
||||
params := callback.Type().Underlying().(*types.Signature).Params()
|
||||
for i := 0; i < params.Len(); i++ {
|
||||
valueTypes = append(valueTypes, b.getLLVMType(params.At(i).Type()))
|
||||
}
|
||||
|
||||
deferFrameType := b.ctx.StructType(valueTypes, false)
|
||||
deferFramePtr := b.CreateBitCast(deferData, llvm.PointerType(deferFrameType, 0), "deferFrame")
|
||||
|
||||
// Extract the params from the struct.
|
||||
var forwardParams []llvm.Value
|
||||
zero := llvm.ConstInt(b.ctx.Int32Type(), 0, false)
|
||||
for i := 0; i < params.Len(); i++ {
|
||||
gep := b.CreateInBoundsGEP(deferFramePtr, []llvm.Value{zero, llvm.ConstInt(b.ctx.Int32Type(), uint64(i+2), false)}, "gep")
|
||||
forwardParam := b.CreateLoad(gep, "param")
|
||||
forwardParams = append(forwardParams, forwardParam)
|
||||
}
|
||||
|
||||
b.createRuntimeCall(db.funcName, forwardParams, "")
|
||||
default:
|
||||
panic("unknown deferred function type")
|
||||
}
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ import (
|
||||
|
||||
// Version of TinyGo.
|
||||
// Update this value before release of new version of software.
|
||||
const Version = "0.14.0-dev"
|
||||
const Version = "0.14.0"
|
||||
|
||||
// GetGorootVersion returns the major and minor version for a given GOROOT path.
|
||||
// If the goroot cannot be determined, (0, 0) is returned.
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
# Hooks for Docker Hub
|
||||
|
||||
Files in this directory are custom commands to be run during the different Docker Hub build phases.
|
||||
|
||||
See https://docs.docker.com/docker-hub/builds/advanced/#custom-build-phase-hooks
|
||||
Executable
+4
@@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
# Docker hub does a recursive clone, then checks the branch out,
|
||||
# so when a PR adds a submodule (or updates it), it fails.
|
||||
git submodule update --init
|
||||
@@ -62,6 +62,10 @@ func (e *evalPackage) hasSideEffects(fn llvm.Value) (*sideEffectResult, *Error)
|
||||
return &sideEffectResult{severity: sideEffectNone}, nil
|
||||
case name == "llvm.dbg.value":
|
||||
return &sideEffectResult{severity: sideEffectNone}, nil
|
||||
case name == "(*sync/atomic.Value).Load" || name == "(*sync/atomic.Value).Store":
|
||||
// These functions do some unsafe pointer loading/storing but are
|
||||
// otherwise safe.
|
||||
return &sideEffectResult{severity: sideEffectLimited}, nil
|
||||
case strings.HasPrefix(name, "llvm.lifetime."):
|
||||
return &sideEffectResult{severity: sideEffectNone}, nil
|
||||
}
|
||||
@@ -122,6 +126,8 @@ func (e *evalPackage) hasSideEffects(fn llvm.Value) (*sideEffectResult, *Error)
|
||||
// External function call. Assume only limited side effects
|
||||
// (no affected globals, etc.).
|
||||
switch child.Name() {
|
||||
case "runtime.alloc":
|
||||
continue
|
||||
case "runtime.typeAssert":
|
||||
continue // implemented in interp
|
||||
case "runtime.interfaceImplements":
|
||||
|
||||
+1
-1
Submodule lib/cmsis-svd updated: 15b462f152...a155cfd832
+1
-1
@@ -165,7 +165,7 @@ func mergeDirectory(goroot, tinygoroot, tmpgoroot, importPath string, overrides
|
||||
// with the TinyGo version. This is the case on some targets.
|
||||
func needsSyscallPackage(buildTags []string) bool {
|
||||
for _, tag := range buildTags {
|
||||
if tag == "baremetal" || tag == "darwin" {
|
||||
if tag == "baremetal" || tag == "darwin" || tag == "nintendoswitch" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -796,6 +796,7 @@ func main() {
|
||||
tags := flag.String("tags", "", "a space-separated list of extra build tags")
|
||||
target := flag.String("target", "", "LLVM target | .json file with TargetSpec")
|
||||
printSize := flag.String("size", "", "print sizes (none, short, full)")
|
||||
printStacks := flag.Bool("print-stacks", false, "print stack sizes of goroutines")
|
||||
nodebug := flag.Bool("no-debug", false, "disable DWARF debug symbol generation")
|
||||
ocdOutput := flag.Bool("ocd-output", false, "print OCD daemon output during debug")
|
||||
port := flag.String("port", "", "flash port")
|
||||
@@ -835,6 +836,7 @@ func main() {
|
||||
VerifyIR: *verifyIR,
|
||||
Debug: !*nodebug,
|
||||
PrintSizes: *printSize,
|
||||
PrintStacks: *printStacks,
|
||||
Tags: *tags,
|
||||
WasmAbi: *wasmAbi,
|
||||
Programmer: *programmer,
|
||||
|
||||
@@ -6,6 +6,7 @@ package main
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
@@ -25,6 +26,8 @@ import (
|
||||
|
||||
const TESTDATA = "testdata"
|
||||
|
||||
var testTarget = flag.String("target", "", "override test target")
|
||||
|
||||
func TestCompiler(t *testing.T) {
|
||||
matches, err := filepath.Glob(filepath.Join(TESTDATA, "*.go"))
|
||||
if err != nil {
|
||||
@@ -44,6 +47,14 @@ func TestCompiler(t *testing.T) {
|
||||
|
||||
sort.Strings(matches)
|
||||
|
||||
if *testTarget != "" {
|
||||
// This makes it possible to run one specific test (instead of all),
|
||||
// which is especially useful to quickly check whether some changes
|
||||
// affect a particular target architecture.
|
||||
runPlatTests(*testTarget, matches, t)
|
||||
return
|
||||
}
|
||||
|
||||
if runtime.GOOS != "windows" {
|
||||
t.Run("Host", func(t *testing.T) {
|
||||
runPlatTests("", matches, t)
|
||||
|
||||
@@ -174,6 +174,11 @@ func EnableIRQ(irq uint32) {
|
||||
NVIC.ISER[irq>>5].Set(1 << (irq & 0x1F))
|
||||
}
|
||||
|
||||
// Disable the given interrupt number.
|
||||
func DisableIRQ(irq uint32) {
|
||||
NVIC.ICER[irq>>5].Set(1 << (irq & 0x1F))
|
||||
}
|
||||
|
||||
// Set the priority of the given interrupt number.
|
||||
// Note that the priority is given as a 0-255 number, where some of the lower
|
||||
// bits are not implemented by the hardware. For example, to set a low interrupt
|
||||
|
||||
@@ -19,6 +19,7 @@ HardFault_Handler:
|
||||
|
||||
// Continue handling this error in Go.
|
||||
bl handleHardFault
|
||||
.size HardFault_Handler, .-HardFault_Handler
|
||||
|
||||
// This is a convenience function for semihosting support.
|
||||
// At some point, this should be replaced by inline assembly.
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
#ifdef __riscv_flen
|
||||
#define NREG 48
|
||||
#define LFREG flw
|
||||
#define SFREG fsw
|
||||
#else
|
||||
#define NREG 16
|
||||
#endif
|
||||
|
||||
#if __riscv_xlen==64
|
||||
#define REGSIZE 8
|
||||
#define SREG sd
|
||||
#define LREG ld
|
||||
#else
|
||||
#define REGSIZE 4
|
||||
#define SREG sw
|
||||
#define LREG lw
|
||||
#endif
|
||||
|
||||
.section .text.handleInterruptASM
|
||||
.global handleInterruptASM
|
||||
.type handleInterruptASM,@function
|
||||
handleInterruptASM:
|
||||
// Save and restore all registers, because the hardware only saves/restores
|
||||
// the pc.
|
||||
// Note: we have to do this in assembly because the "interrupt"="machine"
|
||||
// attribute is broken in LLVM: https://bugs.llvm.org/show_bug.cgi?id=42984
|
||||
addi sp, sp, -NREG*REGSIZE
|
||||
SREG ra, 0*REGSIZE(sp)
|
||||
SREG t0, 1*REGSIZE(sp)
|
||||
SREG t1, 2*REGSIZE(sp)
|
||||
SREG t2, 3*REGSIZE(sp)
|
||||
SREG a0, 4*REGSIZE(sp)
|
||||
SREG a1, 5*REGSIZE(sp)
|
||||
SREG a2, 6*REGSIZE(sp)
|
||||
SREG a3, 7*REGSIZE(sp)
|
||||
SREG a4, 8*REGSIZE(sp)
|
||||
SREG a5, 9*REGSIZE(sp)
|
||||
SREG a6, 10*REGSIZE(sp)
|
||||
SREG a7, 11*REGSIZE(sp)
|
||||
SREG t3, 12*REGSIZE(sp)
|
||||
SREG t4, 13*REGSIZE(sp)
|
||||
SREG t5, 14*REGSIZE(sp)
|
||||
SREG t6, 15*REGSIZE(sp)
|
||||
#ifdef __riscv_flen
|
||||
SFREG f0, (0 + 16)*REGSIZE(sp)
|
||||
SFREG f1, (1 + 16)*REGSIZE(sp)
|
||||
SFREG f2, (2 + 16)*REGSIZE(sp)
|
||||
SFREG f3, (3 + 16)*REGSIZE(sp)
|
||||
SFREG f4, (4 + 16)*REGSIZE(sp)
|
||||
SFREG f5, (5 + 16)*REGSIZE(sp)
|
||||
SFREG f6, (6 + 16)*REGSIZE(sp)
|
||||
SFREG f7, (7 + 16)*REGSIZE(sp)
|
||||
SFREG f8, (8 + 16)*REGSIZE(sp)
|
||||
SFREG f9, (9 + 16)*REGSIZE(sp)
|
||||
SFREG f10,(10 + 16)*REGSIZE(sp)
|
||||
SFREG f11,(11 + 16)*REGSIZE(sp)
|
||||
SFREG f12,(12 + 16)*REGSIZE(sp)
|
||||
SFREG f13,(13 + 16)*REGSIZE(sp)
|
||||
SFREG f14,(14 + 16)*REGSIZE(sp)
|
||||
SFREG f15,(15 + 16)*REGSIZE(sp)
|
||||
SFREG f16,(16 + 16)*REGSIZE(sp)
|
||||
SFREG f17,(17 + 16)*REGSIZE(sp)
|
||||
SFREG f18,(18 + 16)*REGSIZE(sp)
|
||||
SFREG f19,(19 + 16)*REGSIZE(sp)
|
||||
SFREG f20,(20 + 16)*REGSIZE(sp)
|
||||
SFREG f21,(21 + 16)*REGSIZE(sp)
|
||||
SFREG f22,(22 + 16)*REGSIZE(sp)
|
||||
SFREG f23,(23 + 16)*REGSIZE(sp)
|
||||
SFREG f24,(24 + 16)*REGSIZE(sp)
|
||||
SFREG f25,(25 + 16)*REGSIZE(sp)
|
||||
SFREG f26,(26 + 16)*REGSIZE(sp)
|
||||
SFREG f27,(27 + 16)*REGSIZE(sp)
|
||||
SFREG f28,(28 + 16)*REGSIZE(sp)
|
||||
SFREG f29,(29 + 16)*REGSIZE(sp)
|
||||
SFREG f30,(30 + 16)*REGSIZE(sp)
|
||||
SFREG f31,(31 + 16)*REGSIZE(sp)
|
||||
#endif
|
||||
call handleInterrupt
|
||||
#ifdef __riscv_flen
|
||||
LFREG f0, (31 + 16)*REGSIZE(sp)
|
||||
LFREG f1, (30 + 16)*REGSIZE(sp)
|
||||
LFREG f2, (29 + 16)*REGSIZE(sp)
|
||||
LFREG f3, (28 + 16)*REGSIZE(sp)
|
||||
LFREG f4, (27 + 16)*REGSIZE(sp)
|
||||
LFREG f5, (26 + 16)*REGSIZE(sp)
|
||||
LFREG f6, (25 + 16)*REGSIZE(sp)
|
||||
LFREG f7, (24 + 16)*REGSIZE(sp)
|
||||
LFREG f8, (23 + 16)*REGSIZE(sp)
|
||||
LFREG f9, (22 + 16)*REGSIZE(sp)
|
||||
LFREG f10,(21 + 16)*REGSIZE(sp)
|
||||
LFREG f11,(20 + 16)*REGSIZE(sp)
|
||||
LFREG f12,(19 + 16)*REGSIZE(sp)
|
||||
LFREG f13,(18 + 16)*REGSIZE(sp)
|
||||
LFREG f14,(17 + 16)*REGSIZE(sp)
|
||||
LFREG f15,(16 + 16)*REGSIZE(sp)
|
||||
LFREG f16,(15 + 16)*REGSIZE(sp)
|
||||
LFREG f17,(14 + 16)*REGSIZE(sp)
|
||||
LFREG f18,(13 + 16)*REGSIZE(sp)
|
||||
LFREG f19,(12 + 16)*REGSIZE(sp)
|
||||
LFREG f20,(11 + 16)*REGSIZE(sp)
|
||||
LFREG f21,(10 + 16)*REGSIZE(sp)
|
||||
LFREG f22,(9 + 16)*REGSIZE(sp)
|
||||
LFREG f23,(8 + 16)*REGSIZE(sp)
|
||||
LFREG f24,(7 + 16)*REGSIZE(sp)
|
||||
LFREG f25,(6 + 16)*REGSIZE(sp)
|
||||
LFREG f26,(5 + 16)*REGSIZE(sp)
|
||||
LFREG f27,(4 + 16)*REGSIZE(sp)
|
||||
LFREG f28,(3 + 16)*REGSIZE(sp)
|
||||
LFREG f29,(2 + 16)*REGSIZE(sp)
|
||||
LFREG f30,(1 + 16)*REGSIZE(sp)
|
||||
LFREG f31,(0 + 16)*REGSIZE(sp)
|
||||
#endif
|
||||
LREG t6, 15*REGSIZE(sp)
|
||||
LREG t5, 14*REGSIZE(sp)
|
||||
LREG t4, 13*REGSIZE(sp)
|
||||
LREG t3, 12*REGSIZE(sp)
|
||||
LREG a7, 11*REGSIZE(sp)
|
||||
LREG a6, 10*REGSIZE(sp)
|
||||
LREG a5, 9*REGSIZE(sp)
|
||||
LREG a4, 8*REGSIZE(sp)
|
||||
LREG a3, 7*REGSIZE(sp)
|
||||
LREG a2, 6*REGSIZE(sp)
|
||||
LREG a1, 5*REGSIZE(sp)
|
||||
LREG a0, 4*REGSIZE(sp)
|
||||
LREG t2, 3*REGSIZE(sp)
|
||||
LREG t1, 2*REGSIZE(sp)
|
||||
LREG t0, 1*REGSIZE(sp)
|
||||
LREG ra, 0*REGSIZE(sp)
|
||||
addi sp, sp, NREG*REGSIZE
|
||||
mret
|
||||
@@ -9,52 +9,12 @@ _start:
|
||||
// Load the globals pointer. The program will load pointers relative to this
|
||||
// register, so it must be set to the right value on startup.
|
||||
// See: https://gnu-mcu-eclipse.github.io/arch/riscv/programmer/#the-gp-global-pointer-register
|
||||
// Linker relaxations must be disabled to avoid the initialization beign
|
||||
// relaxed with an uninitialized global pointer: mv gp, gp
|
||||
.option push
|
||||
.option norelax
|
||||
la gp, __global_pointer$
|
||||
.option pop
|
||||
|
||||
// Jump to runtime.main
|
||||
call main
|
||||
|
||||
.section .text.handleInterruptASM
|
||||
.global handleInterruptASM
|
||||
.type handleInterruptASM,@function
|
||||
handleInterruptASM:
|
||||
// Save and restore all registers, because the hardware only saves/restores
|
||||
// the pc.
|
||||
// Note: we have to do this in assembly because the "interrupt"="machine"
|
||||
// attribute is broken in LLVM: https://bugs.llvm.org/show_bug.cgi?id=42984
|
||||
addi sp, sp, -64
|
||||
sw ra, 60(sp)
|
||||
sw t0, 56(sp)
|
||||
sw t1, 52(sp)
|
||||
sw t2, 48(sp)
|
||||
sw a0, 44(sp)
|
||||
sw a1, 40(sp)
|
||||
sw a2, 36(sp)
|
||||
sw a3, 32(sp)
|
||||
sw a4, 28(sp)
|
||||
sw a5, 24(sp)
|
||||
sw a6, 20(sp)
|
||||
sw a7, 16(sp)
|
||||
sw t3, 12(sp)
|
||||
sw t4, 8(sp)
|
||||
sw t5, 4(sp)
|
||||
sw t6, 0(sp)
|
||||
call handleInterrupt
|
||||
lw t6, 0(sp)
|
||||
lw t5, 4(sp)
|
||||
lw t4, 8(sp)
|
||||
lw t3, 12(sp)
|
||||
lw a7, 16(sp)
|
||||
lw a6, 20(sp)
|
||||
lw a5, 24(sp)
|
||||
lw a4, 28(sp)
|
||||
lw a3, 32(sp)
|
||||
lw a2, 36(sp)
|
||||
lw a1, 40(sp)
|
||||
lw a0, 44(sp)
|
||||
lw t2, 48(sp)
|
||||
lw t1, 52(sp)
|
||||
lw t0, 56(sp)
|
||||
lw ra, 60(sp)
|
||||
addi sp, sp, 64
|
||||
mret
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
// +build circuitplay_express
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"machine"
|
||||
)
|
||||
|
||||
func init() {
|
||||
enable := machine.PA30
|
||||
enable.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
enable.Set(true)
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// Simplistic example using the DAC on the Circuit Playground Express.
|
||||
//
|
||||
// To actually use the DAC for producing complex waveforms or samples requires a DMA
|
||||
// timer-based playback mechanism which is beyond the scope of this example.
|
||||
package main
|
||||
|
||||
import (
|
||||
"machine"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
speaker := machine.A0
|
||||
speaker.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
|
||||
machine.DAC0.Configure(machine.DACConfig{})
|
||||
|
||||
data := []uint16{0xFFFF, 0x8000, 0x4000, 0x2000, 0x1000, 0x0000}
|
||||
|
||||
for {
|
||||
for _, val := range data {
|
||||
play(val)
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func play(val uint16) {
|
||||
for i := 0; i < 100; i++ {
|
||||
machine.DAC0.Set(val)
|
||||
time.Sleep(2 * time.Millisecond)
|
||||
|
||||
machine.DAC0.Set(0)
|
||||
time.Sleep(2 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// +build pyportal
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"machine"
|
||||
)
|
||||
|
||||
func init() {
|
||||
enable := machine.SPK_SD
|
||||
enable.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
enable.Set(true)
|
||||
}
|
||||
@@ -5,6 +5,8 @@ import (
|
||||
"machine"
|
||||
)
|
||||
|
||||
var timerCh = make(chan struct{}, 1)
|
||||
|
||||
func main() {
|
||||
machine.LED.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||
|
||||
@@ -12,17 +14,18 @@ func main() {
|
||||
arm.SetupSystemTimer(machine.CPUFrequency() / 10)
|
||||
|
||||
for {
|
||||
machine.LED.Low()
|
||||
<-timerCh
|
||||
machine.LED.High()
|
||||
<-timerCh
|
||||
}
|
||||
}
|
||||
|
||||
var led_state bool
|
||||
|
||||
//export SysTick_Handler
|
||||
func timer_isr() {
|
||||
if led_state {
|
||||
machine.LED.Low()
|
||||
} else {
|
||||
machine.LED.High()
|
||||
select {
|
||||
case timerCh <- struct{}{}:
|
||||
default:
|
||||
// The consumer is running behind.
|
||||
}
|
||||
led_state = !led_state
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package task
|
||||
|
||||
import "runtime/interrupt"
|
||||
|
||||
const asserts = false
|
||||
|
||||
// Queue is a FIFO container of tasks.
|
||||
@@ -10,7 +12,9 @@ type Queue struct {
|
||||
|
||||
// Push a task onto the queue.
|
||||
func (q *Queue) Push(t *Task) {
|
||||
i := interrupt.Disable()
|
||||
if asserts && t.Next != nil {
|
||||
interrupt.Restore(i)
|
||||
panic("runtime: pushing a task to a queue with a non-nil Next pointer")
|
||||
}
|
||||
if q.tail != nil {
|
||||
@@ -21,12 +25,15 @@ func (q *Queue) Push(t *Task) {
|
||||
if q.head == nil {
|
||||
q.head = t
|
||||
}
|
||||
interrupt.Restore(i)
|
||||
}
|
||||
|
||||
// Pop a task off of the queue.
|
||||
func (q *Queue) Pop() *Task {
|
||||
i := interrupt.Disable()
|
||||
t := q.head
|
||||
if t == nil {
|
||||
interrupt.Restore(i)
|
||||
return nil
|
||||
}
|
||||
q.head = t.Next
|
||||
@@ -34,11 +41,13 @@ func (q *Queue) Pop() *Task {
|
||||
q.tail = nil
|
||||
}
|
||||
t.Next = nil
|
||||
interrupt.Restore(i)
|
||||
return t
|
||||
}
|
||||
|
||||
// Append pops the contents of another queue and pushes them onto the end of this queue.
|
||||
func (q *Queue) Append(other *Queue) {
|
||||
i := interrupt.Disable()
|
||||
if q.head == nil {
|
||||
q.head = other.head
|
||||
} else {
|
||||
@@ -46,6 +55,15 @@ func (q *Queue) Append(other *Queue) {
|
||||
}
|
||||
q.tail = other.tail
|
||||
other.head, other.tail = nil, nil
|
||||
interrupt.Restore(i)
|
||||
}
|
||||
|
||||
// Empty checks if the queue is empty.
|
||||
func (q *Queue) Empty() bool {
|
||||
i := interrupt.Disable()
|
||||
empty := q.head == nil
|
||||
interrupt.Restore(i)
|
||||
return empty
|
||||
}
|
||||
|
||||
// Stack is a LIFO container of tasks.
|
||||
@@ -57,19 +75,24 @@ type Stack struct {
|
||||
|
||||
// Push a task onto the stack.
|
||||
func (s *Stack) Push(t *Task) {
|
||||
i := interrupt.Disable()
|
||||
if asserts && t.Next != nil {
|
||||
interrupt.Restore(i)
|
||||
panic("runtime: pushing a task to a stack with a non-nil Next pointer")
|
||||
}
|
||||
s.top, t.Next = t, s.top
|
||||
interrupt.Restore(i)
|
||||
}
|
||||
|
||||
// Pop a task off of the stack.
|
||||
func (s *Stack) Pop() *Task {
|
||||
i := interrupt.Disable()
|
||||
t := s.top
|
||||
if t != nil {
|
||||
s.top = t.Next
|
||||
t.Next = nil
|
||||
}
|
||||
interrupt.Restore(i)
|
||||
return t
|
||||
}
|
||||
|
||||
@@ -89,10 +112,13 @@ func (t *Task) tail() *Task {
|
||||
// Queue moves the contents of the stack into a queue.
|
||||
// Elements can be popped from the queue in the same order that they would be popped from the stack.
|
||||
func (s *Stack) Queue() Queue {
|
||||
i := interrupt.Disable()
|
||||
head := s.top
|
||||
s.top = nil
|
||||
return Queue{
|
||||
q := Queue{
|
||||
head: head,
|
||||
tail: head.tail(),
|
||||
}
|
||||
interrupt.Restore(i)
|
||||
return q
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ const (
|
||||
// Digital pins
|
||||
D0 Pin = PE0
|
||||
D1 Pin = PE1
|
||||
D2 Pin = PE6
|
||||
D2 Pin = PE4
|
||||
D3 Pin = PE5
|
||||
D4 Pin = PG5
|
||||
D5 Pin = PE3
|
||||
|
||||
@@ -66,15 +66,15 @@ const (
|
||||
|
||||
// SPI pins
|
||||
const (
|
||||
SPI0_SCK_PIN Pin = D13 // SCK: SERCOM1/PAD[1]
|
||||
SPI0_MOSI_PIN Pin = D11 // MOSI: SERCOM1/PAD[0]
|
||||
SPI0_MISO_PIN Pin = D12 // MISO: SERCOM1/PAD[3]
|
||||
SPI0_SCK_PIN Pin = D13 // SCK: SERCOM1/PAD[1]
|
||||
SPI0_SDO_PIN Pin = D11 // SDO: SERCOM1/PAD[0]
|
||||
SPI0_SDI_PIN Pin = D12 // SDI: SERCOM1/PAD[3]
|
||||
)
|
||||
|
||||
// NINA-W102 Pins
|
||||
const (
|
||||
NINA_MOSI Pin = PA12
|
||||
NINA_MISO Pin = PA13
|
||||
NINA_SDO Pin = PA12
|
||||
NINA_SDI Pin = PA13
|
||||
NINA_CS Pin = PA14
|
||||
NINA_SCK Pin = PA15
|
||||
NINA_GPIO0 Pin = PA27
|
||||
|
||||
@@ -74,9 +74,9 @@ func init() {
|
||||
|
||||
// SPI pins
|
||||
const (
|
||||
SPI0_SCK_PIN = PA5
|
||||
SPI0_MOSI_PIN = PA7
|
||||
SPI0_MISO_PIN = PA6
|
||||
SPI0_SCK_PIN = PA5
|
||||
SPI0_SDO_PIN = PA7
|
||||
SPI0_SDI_PIN = PA6
|
||||
)
|
||||
|
||||
// I2C pins
|
||||
|
||||
@@ -72,9 +72,9 @@ const (
|
||||
|
||||
// SPI pins (internal flash)
|
||||
const (
|
||||
SPI0_SCK_PIN = P0_19 // SCK
|
||||
SPI0_MOSI_PIN = P0_21 // MOSI
|
||||
SPI0_MISO_PIN = P0_23 // MISO
|
||||
SPI0_SCK_PIN = P0_19 // SCK
|
||||
SPI0_SDO_PIN = P0_21 // SDO
|
||||
SPI0_SDI_PIN = P0_23 // SDI
|
||||
)
|
||||
|
||||
// USB CDC identifiers
|
||||
|
||||
@@ -77,9 +77,9 @@ const (
|
||||
|
||||
// SPI pins (internal flash)
|
||||
const (
|
||||
SPI0_SCK_PIN = PA21 // SCK: SERCOM3/PAD[3]
|
||||
SPI0_MOSI_PIN = PA20 // MOSI: SERCOM3/PAD[2]
|
||||
SPI0_MISO_PIN = PA16 // MISO: SERCOM3/PAD[0]
|
||||
SPI0_SCK_PIN = PA21 // SCK: SERCOM3/PAD[3]
|
||||
SPI0_SDO_PIN = PA20 // SDO: SERCOM3/PAD[2]
|
||||
SPI0_SDI_PIN = PA16 // SDI: SERCOM3/PAD[0]
|
||||
)
|
||||
|
||||
// I2S pins
|
||||
|
||||
@@ -78,7 +78,7 @@ const (
|
||||
|
||||
// 240x240 ST7789 display is connected to these pins (use RowOffset = 80)
|
||||
TFT_SCK = D29
|
||||
TFT_MOSI = D30
|
||||
TFT_SDO = D30
|
||||
TFT_CS = D31
|
||||
TFT_DC = D32
|
||||
TFT_RESET = D33
|
||||
@@ -116,9 +116,9 @@ const (
|
||||
|
||||
// SPI pins
|
||||
const (
|
||||
SPI0_SCK_PIN = D13 // SCK
|
||||
SPI0_MOSI_PIN = D15 // MOSI
|
||||
SPI0_MISO_PIN = D14 // MISO
|
||||
SPI0_SCK_PIN = D13 // SCK
|
||||
SPI0_SDO_PIN = D15 // SDO
|
||||
SPI0_SDI_PIN = D14 // SDI
|
||||
)
|
||||
|
||||
// USB CDC identifiers
|
||||
|
||||
@@ -83,9 +83,9 @@ var (
|
||||
|
||||
// SPI pins
|
||||
const (
|
||||
SPI0_SCK_PIN = PB11 // SCK: SERCOM4/PAD[3]
|
||||
SPI0_MOSI_PIN = PB10 // MOSI: SERCOM4/PAD[2]
|
||||
SPI0_MISO_PIN = PA12 // MISO: SERCOM4/PAD[0]
|
||||
SPI0_SCK_PIN = PB11 // SCK: SERCOM4/PAD[3]
|
||||
SPI0_SDO_PIN = PB10 // SDO: SERCOM4/PAD[2]
|
||||
SPI0_SDI_PIN = PA12 // SDI: SERCOM4/PAD[0]
|
||||
)
|
||||
|
||||
// SPI on the Feather M0.
|
||||
|
||||
@@ -63,9 +63,9 @@ const (
|
||||
|
||||
// SPI pins
|
||||
const (
|
||||
SPI0_SCK_PIN = D25 // SCK: SERCOM1/PAD[1]
|
||||
SPI0_MOSI_PIN = D24 // MOSI: SERCOM1/PAD[3]
|
||||
SPI0_MISO_PIN = D23 // MISO: SERCOM1/PAD[2]
|
||||
SPI0_SCK_PIN = D25 // SCK: SERCOM1/PAD[1]
|
||||
SPI0_SDO_PIN = D24 // SDO: SERCOM1/PAD[3]
|
||||
SPI0_SDI_PIN = D23 // SDI: SERCOM1/PAD[2]
|
||||
)
|
||||
|
||||
// USB CDC identifiers
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
// +build feather_nrf52840
|
||||
|
||||
package machine
|
||||
|
||||
const HasLowFrequencyCrystal = true
|
||||
|
||||
// GPIO Pins
|
||||
const (
|
||||
D0 = P0_25 // UART TX
|
||||
D1 = P0_24 // UART RX
|
||||
D2 = P0_10 // NFC2
|
||||
D3 = P1_15 // LED1
|
||||
D4 = P1_10 // LED2
|
||||
D5 = P1_08
|
||||
D6 = P0_07
|
||||
D7 = P1_02 // Button
|
||||
D8 = P0_16 // NeoPixel
|
||||
D9 = P0_26
|
||||
D10 = P0_27
|
||||
D11 = P0_06
|
||||
D12 = P0_08
|
||||
D13 = P1_09
|
||||
D14 = P0_04 // A0
|
||||
D15 = P0_05 // A1
|
||||
D16 = P0_30 // A2
|
||||
D17 = P0_28 // A3
|
||||
D18 = P0_02 // A4
|
||||
D19 = P0_03 // A5
|
||||
D20 = P0_29 // Battery
|
||||
D21 = P0_31 // AREF
|
||||
D22 = P0_12 // I2C SDA
|
||||
D23 = P0_11 // I2C SCL
|
||||
D24 = P0_15 // SPI MISO
|
||||
D25 = P0_13 // SPI MOSI
|
||||
D26 = P0_14 // SPI SCK
|
||||
D27 = P0_19 // QSPI CLK
|
||||
D28 = P0_20 // QSPI CS
|
||||
D29 = P0_17 // QSPI Data 0
|
||||
D30 = P0_22 // QSPI Data 1
|
||||
D31 = P0_23 // QSPI Data 2
|
||||
D32 = P0_21 // QSPI Data 3
|
||||
D33 = P0_09 // NFC1 (test point on bottom of board)
|
||||
)
|
||||
|
||||
// Analog Pins
|
||||
const (
|
||||
A0 = D14
|
||||
A1 = D15
|
||||
A2 = D16
|
||||
A3 = D17
|
||||
A4 = D18
|
||||
A5 = D19
|
||||
A6 = D20 // Battery
|
||||
A7 = D21 // ARef
|
||||
)
|
||||
|
||||
const (
|
||||
LED = D3
|
||||
LED1 = LED
|
||||
LED2 = D4
|
||||
NEOPIXEL = D8
|
||||
BUTTON = D7
|
||||
|
||||
QSPI_SCK = D27
|
||||
QSPI_CS = D28
|
||||
QSPI_DATA0 = D29
|
||||
QSPI_DATA1 = D30
|
||||
QSPI_DATA2 = D31
|
||||
QSPI_DATA3 = D32
|
||||
)
|
||||
|
||||
// UART0 pins (logical UART1)
|
||||
const (
|
||||
UART_RX_PIN = D0
|
||||
UART_TX_PIN = D1
|
||||
)
|
||||
|
||||
// UART0 is the USB device
|
||||
var (
|
||||
UART0 = USB
|
||||
)
|
||||
|
||||
// I2C pins
|
||||
const (
|
||||
SDA_PIN = D22 // I2C0 external
|
||||
SCL_PIN = D23 // I2C0 external
|
||||
)
|
||||
|
||||
// SPI pins
|
||||
const (
|
||||
SPI0_SCK_PIN = D26 // SCK
|
||||
SPI0_SDO_PIN = D25 // SDO
|
||||
SPI0_SDI_PIN = D24 // SDI
|
||||
)
|
||||
|
||||
// USB CDC identifiers
|
||||
const (
|
||||
usb_STRING_PRODUCT = "Feather nRF52840 Express"
|
||||
usb_STRING_MANUFACTURER = "Adafruit Industries LLC"
|
||||
)
|
||||
|
||||
var (
|
||||
usb_VID uint16 = 0x239A
|
||||
usb_PID uint16 = 0x802A
|
||||
)
|
||||
@@ -43,13 +43,13 @@ const (
|
||||
|
||||
// SPI pins
|
||||
const (
|
||||
SPI0_SCK_PIN = NoPin
|
||||
SPI0_MOSI_PIN = NoPin
|
||||
SPI0_MISO_PIN = NoPin
|
||||
SPI0_SCK_PIN = NoPin
|
||||
SPI0_SDO_PIN = NoPin
|
||||
SPI0_SDI_PIN = NoPin
|
||||
|
||||
SPI1_SCK_PIN = D13
|
||||
SPI1_MOSI_PIN = D11
|
||||
SPI1_MISO_PIN = D12
|
||||
SPI1_SCK_PIN = D13
|
||||
SPI1_SDO_PIN = D11
|
||||
SPI1_SDI_PIN = D12
|
||||
)
|
||||
|
||||
// I2C pins
|
||||
|
||||
@@ -83,9 +83,9 @@ var (
|
||||
|
||||
// SPI pins
|
||||
const (
|
||||
SPI0_SCK_PIN = PB11 // SCK: SERCOM4/PAD[3]
|
||||
SPI0_MOSI_PIN = PB10 // MOSI: SERCOM4/PAD[2]
|
||||
SPI0_MISO_PIN = PA12 // MISO: SERCOM4/PAD[0]
|
||||
SPI0_SCK_PIN = PB11 // SCK: SERCOM4/PAD[3]
|
||||
SPI0_SDO_PIN = PB10 // SDO: SERCOM4/PAD[2]
|
||||
SPI0_SDI_PIN = PA12 // SDI: SERCOM4/PAD[0]
|
||||
)
|
||||
|
||||
// SPI on the ItsyBitsy M0.
|
||||
@@ -98,10 +98,10 @@ var (
|
||||
|
||||
// "Internal" SPI pins; SPI flash is attached to these on ItsyBitsy M0
|
||||
const (
|
||||
SPI1_CS_PIN = PA27
|
||||
SPI1_SCK_PIN = PB23
|
||||
SPI1_MOSI_PIN = PB22
|
||||
SPI1_MISO_PIN = PB03
|
||||
SPI1_CS_PIN = PA27
|
||||
SPI1_SCK_PIN = PB23
|
||||
SPI1_SDO_PIN = PB22
|
||||
SPI1_SDI_PIN = PB03
|
||||
)
|
||||
|
||||
// "Internal" SPI on Sercom 5
|
||||
|
||||
@@ -62,9 +62,9 @@ const (
|
||||
|
||||
// SPI pins
|
||||
const (
|
||||
SPI0_SCK_PIN = PA01 // SCK: SERCOM1/PAD[1]
|
||||
SPI0_MOSI_PIN = PA00 // MOSI: SERCOM1/PAD[0]
|
||||
SPI0_MISO_PIN = PB23 // MISO: SERCOM1/PAD[3]
|
||||
SPI0_SCK_PIN = PA01 // SCK: SERCOM1/PAD[1]
|
||||
SPI0_SDO_PIN = PA00 // SDO: SERCOM1/PAD[0]
|
||||
SPI0_SDI_PIN = PB23 // SDI: SERCOM1/PAD[3]
|
||||
)
|
||||
|
||||
// USB CDC identifiers
|
||||
|
||||
@@ -0,0 +1,354 @@
|
||||
// +build maixbit
|
||||
|
||||
// Chip datasheet: https://s3.cn-north-1.amazonaws.com.cn/dl.kendryte.com/documents/kendryte_datasheet_20181011163248_en.pdf
|
||||
|
||||
package machine
|
||||
|
||||
// K210 IO pins.
|
||||
const (
|
||||
P00 Pin = 0
|
||||
P01 Pin = 1
|
||||
P02 Pin = 2
|
||||
P03 Pin = 3
|
||||
P04 Pin = 4
|
||||
P05 Pin = 5
|
||||
P06 Pin = 6
|
||||
P07 Pin = 7
|
||||
P08 Pin = 8
|
||||
P09 Pin = 9
|
||||
P10 Pin = 10
|
||||
P11 Pin = 11
|
||||
P12 Pin = 12
|
||||
P13 Pin = 13
|
||||
P14 Pin = 14
|
||||
P15 Pin = 15
|
||||
P16 Pin = 16
|
||||
P17 Pin = 17
|
||||
P18 Pin = 18
|
||||
P19 Pin = 19
|
||||
P20 Pin = 20
|
||||
P21 Pin = 21
|
||||
P22 Pin = 22
|
||||
P23 Pin = 23
|
||||
P24 Pin = 24
|
||||
P25 Pin = 25
|
||||
P26 Pin = 26
|
||||
P27 Pin = 27
|
||||
P28 Pin = 28
|
||||
P29 Pin = 29
|
||||
P30 Pin = 30
|
||||
P31 Pin = 31
|
||||
P32 Pin = 32
|
||||
P33 Pin = 33
|
||||
P34 Pin = 34
|
||||
P35 Pin = 35
|
||||
P36 Pin = 36
|
||||
P37 Pin = 37
|
||||
P38 Pin = 38
|
||||
P39 Pin = 39
|
||||
P40 Pin = 40
|
||||
P41 Pin = 41
|
||||
P42 Pin = 42
|
||||
P43 Pin = 43
|
||||
P44 Pin = 44
|
||||
P45 Pin = 45
|
||||
P46 Pin = 46
|
||||
P47 Pin = 47
|
||||
)
|
||||
|
||||
type FPIOAFunction uint8
|
||||
|
||||
// Every pin on the Kendryte K210 is assigned to an FPIOA function.
|
||||
// Each pin can be configured with every function below.
|
||||
const (
|
||||
FUNC_JTAG_TCLK FPIOAFunction = 0 // JTAG Test Clock
|
||||
FUNC_JTAG_TDI FPIOAFunction = 1 // JTAG Test Data In
|
||||
FUNC_JTAG_TMS FPIOAFunction = 2 // JTAG Test Mode Select
|
||||
FUNC_JTAG_TDO FPIOAFunction = 3 // JTAG Test Data Out
|
||||
FUNC_SPI0_D0 FPIOAFunction = 4 // SPI0 Data 0
|
||||
FUNC_SPI0_D1 FPIOAFunction = 5 // SPI0 Data 1
|
||||
FUNC_SPI0_D2 FPIOAFunction = 6 // SPI0 Data 2
|
||||
FUNC_SPI0_D3 FPIOAFunction = 7 // SPI0 Data 3
|
||||
FUNC_SPI0_D4 FPIOAFunction = 8 // SPI0 Data 4
|
||||
FUNC_SPI0_D5 FPIOAFunction = 9 // SPI0 Data 5
|
||||
FUNC_SPI0_D6 FPIOAFunction = 10 // SPI0 Data 6
|
||||
FUNC_SPI0_D7 FPIOAFunction = 11 // SPI0 Data 7
|
||||
FUNC_SPI0_SS0 FPIOAFunction = 12 // SPI0 Chip Select 0
|
||||
FUNC_SPI0_SS1 FPIOAFunction = 13 // SPI0 Chip Select 1
|
||||
FUNC_SPI0_SS2 FPIOAFunction = 14 // SPI0 Chip Select 2
|
||||
FUNC_SPI0_SS3 FPIOAFunction = 15 // SPI0 Chip Select 3
|
||||
FUNC_SPI0_ARB FPIOAFunction = 16 // SPI0 Arbitration
|
||||
FUNC_SPI0_SCLK FPIOAFunction = 17 // SPI0 Serial Clock
|
||||
FUNC_UARTHS_RX FPIOAFunction = 18 // UART High speed Receiver
|
||||
FUNC_UARTHS_TX FPIOAFunction = 19 // UART High speed Transmitter
|
||||
FUNC_RESV6 FPIOAFunction = 20 // Reserved function
|
||||
FUNC_RESV7 FPIOAFunction = 21 // Reserved function
|
||||
FUNC_CLK_SPI1 FPIOAFunction = 22 // Clock SPI1
|
||||
FUNC_CLK_I2C1 FPIOAFunction = 23 // Clock I2C1
|
||||
FUNC_GPIOHS0 FPIOAFunction = 24 // GPIO High speed 0
|
||||
FUNC_GPIOHS1 FPIOAFunction = 25 // GPIO High speed 1
|
||||
FUNC_GPIOHS2 FPIOAFunction = 26 // GPIO High speed 2
|
||||
FUNC_GPIOHS3 FPIOAFunction = 27 // GPIO High speed 3
|
||||
FUNC_GPIOHS4 FPIOAFunction = 28 // GPIO High speed 4
|
||||
FUNC_GPIOHS5 FPIOAFunction = 29 // GPIO High speed 5
|
||||
FUNC_GPIOHS6 FPIOAFunction = 30 // GPIO High speed 6
|
||||
FUNC_GPIOHS7 FPIOAFunction = 31 // GPIO High speed 7
|
||||
FUNC_GPIOHS8 FPIOAFunction = 32 // GPIO High speed 8
|
||||
FUNC_GPIOHS9 FPIOAFunction = 33 // GPIO High speed 9
|
||||
FUNC_GPIOHS10 FPIOAFunction = 34 // GPIO High speed 10
|
||||
FUNC_GPIOHS11 FPIOAFunction = 35 // GPIO High speed 11
|
||||
FUNC_GPIOHS12 FPIOAFunction = 36 // GPIO High speed 12
|
||||
FUNC_GPIOHS13 FPIOAFunction = 37 // GPIO High speed 13
|
||||
FUNC_GPIOHS14 FPIOAFunction = 38 // GPIO High speed 14
|
||||
FUNC_GPIOHS15 FPIOAFunction = 39 // GPIO High speed 15
|
||||
FUNC_GPIOHS16 FPIOAFunction = 40 // GPIO High speed 16
|
||||
FUNC_GPIOHS17 FPIOAFunction = 41 // GPIO High speed 17
|
||||
FUNC_GPIOHS18 FPIOAFunction = 42 // GPIO High speed 18
|
||||
FUNC_GPIOHS19 FPIOAFunction = 43 // GPIO High speed 19
|
||||
FUNC_GPIOHS20 FPIOAFunction = 44 // GPIO High speed 20
|
||||
FUNC_GPIOHS21 FPIOAFunction = 45 // GPIO High speed 21
|
||||
FUNC_GPIOHS22 FPIOAFunction = 46 // GPIO High speed 22
|
||||
FUNC_GPIOHS23 FPIOAFunction = 47 // GPIO High speed 23
|
||||
FUNC_GPIOHS24 FPIOAFunction = 48 // GPIO High speed 24
|
||||
FUNC_GPIOHS25 FPIOAFunction = 49 // GPIO High speed 25
|
||||
FUNC_GPIOHS26 FPIOAFunction = 50 // GPIO High speed 26
|
||||
FUNC_GPIOHS27 FPIOAFunction = 51 // GPIO High speed 27
|
||||
FUNC_GPIOHS28 FPIOAFunction = 52 // GPIO High speed 28
|
||||
FUNC_GPIOHS29 FPIOAFunction = 53 // GPIO High speed 29
|
||||
FUNC_GPIOHS30 FPIOAFunction = 54 // GPIO High speed 30
|
||||
FUNC_GPIOHS31 FPIOAFunction = 55 // GPIO High speed 31
|
||||
FUNC_GPIO0 FPIOAFunction = 56 // GPIO pin 0
|
||||
FUNC_GPIO1 FPIOAFunction = 57 // GPIO pin 1
|
||||
FUNC_GPIO2 FPIOAFunction = 58 // GPIO pin 2
|
||||
FUNC_GPIO3 FPIOAFunction = 59 // GPIO pin 3
|
||||
FUNC_GPIO4 FPIOAFunction = 60 // GPIO pin 4
|
||||
FUNC_GPIO5 FPIOAFunction = 61 // GPIO pin 5
|
||||
FUNC_GPIO6 FPIOAFunction = 62 // GPIO pin 6
|
||||
FUNC_GPIO7 FPIOAFunction = 63 // GPIO pin 7
|
||||
FUNC_UART1_RX FPIOAFunction = 64 // UART1 Receiver
|
||||
FUNC_UART1_TX FPIOAFunction = 65 // UART1 Transmitter
|
||||
FUNC_UART2_RX FPIOAFunction = 66 // UART2 Receiver
|
||||
FUNC_UART2_TX FPIOAFunction = 67 // UART2 Transmitter
|
||||
FUNC_UART3_RX FPIOAFunction = 68 // UART3 Receiver
|
||||
FUNC_UART3_TX FPIOAFunction = 69 // UART3 Transmitter
|
||||
FUNC_SPI1_D0 FPIOAFunction = 70 // SPI1 Data 0
|
||||
FUNC_SPI1_D1 FPIOAFunction = 71 // SPI1 Data 1
|
||||
FUNC_SPI1_D2 FPIOAFunction = 72 // SPI1 Data 2
|
||||
FUNC_SPI1_D3 FPIOAFunction = 73 // SPI1 Data 3
|
||||
FUNC_SPI1_D4 FPIOAFunction = 74 // SPI1 Data 4
|
||||
FUNC_SPI1_D5 FPIOAFunction = 75 // SPI1 Data 5
|
||||
FUNC_SPI1_D6 FPIOAFunction = 76 // SPI1 Data 6
|
||||
FUNC_SPI1_D7 FPIOAFunction = 77 // SPI1 Data 7
|
||||
FUNC_SPI1_SS0 FPIOAFunction = 78 // SPI1 Chip Select 0
|
||||
FUNC_SPI1_SS1 FPIOAFunction = 79 // SPI1 Chip Select 1
|
||||
FUNC_SPI1_SS2 FPIOAFunction = 80 // SPI1 Chip Select 2
|
||||
FUNC_SPI1_SS3 FPIOAFunction = 81 // SPI1 Chip Select 3
|
||||
FUNC_SPI1_ARB FPIOAFunction = 82 // SPI1 Arbitration
|
||||
FUNC_SPI1_SCLK FPIOAFunction = 83 // SPI1 Serial Clock
|
||||
FUNC_SPI_PERIPHERAL_D0 FPIOAFunction = 84 // SPI Peripheral Data 0
|
||||
FUNC_SPI_PERIPHERAL_SS FPIOAFunction = 85 // SPI Peripheral Select
|
||||
FUNC_SPI_PERIPHERAL_SCLK FPIOAFunction = 86 // SPI Peripheral Serial Clock
|
||||
FUNC_I2S0_MCLK FPIOAFunction = 87 // I2S0 Main Clock
|
||||
FUNC_I2S0_SCLK FPIOAFunction = 88 // I2S0 Serial Clock(BCLK)
|
||||
FUNC_I2S0_WS FPIOAFunction = 89 // I2S0 Word Select(LRCLK)
|
||||
FUNC_I2S0_IN_D0 FPIOAFunction = 90 // I2S0 Serial Data Input 0
|
||||
FUNC_I2S0_IN_D1 FPIOAFunction = 91 // I2S0 Serial Data Input 1
|
||||
FUNC_I2S0_IN_D2 FPIOAFunction = 92 // I2S0 Serial Data Input 2
|
||||
FUNC_I2S0_IN_D3 FPIOAFunction = 93 // I2S0 Serial Data Input 3
|
||||
FUNC_I2S0_OUT_D0 FPIOAFunction = 94 // I2S0 Serial Data Output 0
|
||||
FUNC_I2S0_OUT_D1 FPIOAFunction = 95 // I2S0 Serial Data Output 1
|
||||
FUNC_I2S0_OUT_D2 FPIOAFunction = 96 // I2S0 Serial Data Output 2
|
||||
FUNC_I2S0_OUT_D3 FPIOAFunction = 97 // I2S0 Serial Data Output 3
|
||||
FUNC_I2S1_MCLK FPIOAFunction = 98 // I2S1 Main Clock
|
||||
FUNC_I2S1_SCLK FPIOAFunction = 99 // I2S1 Serial Clock(BCLK)
|
||||
FUNC_I2S1_WS FPIOAFunction = 100 // I2S1 Word Select(LRCLK)
|
||||
FUNC_I2S1_IN_D0 FPIOAFunction = 101 // I2S1 Serial Data Input 0
|
||||
FUNC_I2S1_IN_D1 FPIOAFunction = 102 // I2S1 Serial Data Input 1
|
||||
FUNC_I2S1_IN_D2 FPIOAFunction = 103 // I2S1 Serial Data Input 2
|
||||
FUNC_I2S1_IN_D3 FPIOAFunction = 104 // I2S1 Serial Data Input 3
|
||||
FUNC_I2S1_OUT_D0 FPIOAFunction = 105 // I2S1 Serial Data Output 0
|
||||
FUNC_I2S1_OUT_D1 FPIOAFunction = 106 // I2S1 Serial Data Output 1
|
||||
FUNC_I2S1_OUT_D2 FPIOAFunction = 107 // I2S1 Serial Data Output 2
|
||||
FUNC_I2S1_OUT_D3 FPIOAFunction = 108 // I2S1 Serial Data Output 3
|
||||
FUNC_I2S2_MCLK FPIOAFunction = 109 // I2S2 Main Clock
|
||||
FUNC_I2S2_SCLK FPIOAFunction = 110 // I2S2 Serial Clock(BCLK)
|
||||
FUNC_I2S2_WS FPIOAFunction = 111 // I2S2 Word Select(LRCLK)
|
||||
FUNC_I2S2_IN_D0 FPIOAFunction = 112 // I2S2 Serial Data Input 0
|
||||
FUNC_I2S2_IN_D1 FPIOAFunction = 113 // I2S2 Serial Data Input 1
|
||||
FUNC_I2S2_IN_D2 FPIOAFunction = 114 // I2S2 Serial Data Input 2
|
||||
FUNC_I2S2_IN_D3 FPIOAFunction = 115 // I2S2 Serial Data Input 3
|
||||
FUNC_I2S2_OUT_D0 FPIOAFunction = 116 // I2S2 Serial Data Output 0
|
||||
FUNC_I2S2_OUT_D1 FPIOAFunction = 117 // I2S2 Serial Data Output 1
|
||||
FUNC_I2S2_OUT_D2 FPIOAFunction = 118 // I2S2 Serial Data Output 2
|
||||
FUNC_I2S2_OUT_D3 FPIOAFunction = 119 // I2S2 Serial Data Output 3
|
||||
FUNC_RESV0 FPIOAFunction = 120 // Reserved function
|
||||
FUNC_RESV1 FPIOAFunction = 121 // Reserved function
|
||||
FUNC_RESV2 FPIOAFunction = 122 // Reserved function
|
||||
FUNC_RESV3 FPIOAFunction = 123 // Reserved function
|
||||
FUNC_RESV4 FPIOAFunction = 124 // Reserved function
|
||||
FUNC_RESV5 FPIOAFunction = 125 // Reserved function
|
||||
FUNC_I2C0_SCLK FPIOAFunction = 126 // I2C0 Serial Clock
|
||||
FUNC_I2C0_SDA FPIOAFunction = 127 // I2C0 Serial Data
|
||||
FUNC_I2C1_SCLK FPIOAFunction = 128 // I2C1 Serial Clock
|
||||
FUNC_I2C1_SDA FPIOAFunction = 129 // I2C1 Serial Data
|
||||
FUNC_I2C2_SCLK FPIOAFunction = 130 // I2C2 Serial Clock
|
||||
FUNC_I2C2_SDA FPIOAFunction = 131 // I2C2 Serial Data
|
||||
FUNC_CMOS_XCLK FPIOAFunction = 132 // DVP System Clock
|
||||
FUNC_CMOS_RST FPIOAFunction = 133 // DVP System Reset
|
||||
FUNC_CMOS_PWDN FPIOAFunction = 134 // DVP Power Down Mode
|
||||
FUNC_CMOS_VSYNC FPIOAFunction = 135 // DVP Vertical Sync
|
||||
FUNC_CMOS_HREF FPIOAFunction = 136 // DVP Horizontal Reference output
|
||||
FUNC_CMOS_PCLK FPIOAFunction = 137 // Pixel Clock
|
||||
FUNC_CMOS_D0 FPIOAFunction = 138 // Data Bit 0
|
||||
FUNC_CMOS_D1 FPIOAFunction = 139 // Data Bit 1
|
||||
FUNC_CMOS_D2 FPIOAFunction = 140 // Data Bit 2
|
||||
FUNC_CMOS_D3 FPIOAFunction = 141 // Data Bit 3
|
||||
FUNC_CMOS_D4 FPIOAFunction = 142 // Data Bit 4
|
||||
FUNC_CMOS_D5 FPIOAFunction = 143 // Data Bit 5
|
||||
FUNC_CMOS_D6 FPIOAFunction = 144 // Data Bit 6
|
||||
FUNC_CMOS_D7 FPIOAFunction = 145 // Data Bit 7
|
||||
FUNC_SCCB_SCLK FPIOAFunction = 146 // SCCB Serial Clock
|
||||
FUNC_SCCB_SDA FPIOAFunction = 147 // SCCB Serial Data
|
||||
FUNC_UART1_CTS FPIOAFunction = 148 // UART1 Clear To Send
|
||||
FUNC_UART1_DSR FPIOAFunction = 149 // UART1 Data Set Ready
|
||||
FUNC_UART1_DCD FPIOAFunction = 150 // UART1 Data Carrier Detect
|
||||
FUNC_UART1_RI FPIOAFunction = 151 // UART1 Ring Indicator
|
||||
FUNC_UART1_SIR_IN FPIOAFunction = 152 // UART1 Serial Infrared Input
|
||||
FUNC_UART1_DTR FPIOAFunction = 153 // UART1 Data Terminal Ready
|
||||
FUNC_UART1_RTS FPIOAFunction = 154 // UART1 Request To Send
|
||||
FUNC_UART1_OUT2 FPIOAFunction = 155 // UART1 User-designated Output 2
|
||||
FUNC_UART1_OUT1 FPIOAFunction = 156 // UART1 User-designated Output 1
|
||||
FUNC_UART1_SIR_OUT FPIOAFunction = 157 // UART1 Serial Infrared Output
|
||||
FUNC_UART1_BAUD FPIOAFunction = 158 // UART1 Transmit Clock Output
|
||||
FUNC_UART1_RE FPIOAFunction = 159 // UART1 Receiver Output Enable
|
||||
FUNC_UART1_DE FPIOAFunction = 160 // UART1 Driver Output Enable
|
||||
FUNC_UART1_RS485_EN FPIOAFunction = 161 // UART1 RS485 Enable
|
||||
FUNC_UART2_CTS FPIOAFunction = 162 // UART2 Clear To Send
|
||||
FUNC_UART2_DSR FPIOAFunction = 163 // UART2 Data Set Ready
|
||||
FUNC_UART2_DCD FPIOAFunction = 164 // UART2 Data Carrier Detect
|
||||
FUNC_UART2_RI FPIOAFunction = 165 // UART2 Ring Indicator
|
||||
FUNC_UART2_SIR_IN FPIOAFunction = 166 // UART2 Serial Infrared Input
|
||||
FUNC_UART2_DTR FPIOAFunction = 167 // UART2 Data Terminal Ready
|
||||
FUNC_UART2_RTS FPIOAFunction = 168 // UART2 Request To Send
|
||||
FUNC_UART2_OUT2 FPIOAFunction = 169 // UART2 User-designated Output 2
|
||||
FUNC_UART2_OUT1 FPIOAFunction = 170 // UART2 User-designated Output 1
|
||||
FUNC_UART2_SIR_OUT FPIOAFunction = 171 // UART2 Serial Infrared Output
|
||||
FUNC_UART2_BAUD FPIOAFunction = 172 // UART2 Transmit Clock Output
|
||||
FUNC_UART2_RE FPIOAFunction = 173 // UART2 Receiver Output Enable
|
||||
FUNC_UART2_DE FPIOAFunction = 174 // UART2 Driver Output Enable
|
||||
FUNC_UART2_RS485_EN FPIOAFunction = 175 // UART2 RS485 Enable
|
||||
FUNC_UART3_CTS FPIOAFunction = 176 // UART3 Clear To Send
|
||||
FUNC_UART3_DSR FPIOAFunction = 177 // UART3 Data Set Ready
|
||||
FUNC_UART3_DCD FPIOAFunction = 178 // UART3 Data Carrier Detect
|
||||
FUNC_UART3_RI FPIOAFunction = 179 // UART3 Ring Indicator
|
||||
FUNC_UART3_SIR_IN FPIOAFunction = 180 // UART3 Serial Infrared Input
|
||||
FUNC_UART3_DTR FPIOAFunction = 181 // UART3 Data Terminal Ready
|
||||
FUNC_UART3_RTS FPIOAFunction = 182 // UART3 Request To Send
|
||||
FUNC_UART3_OUT2 FPIOAFunction = 183 // UART3 User-designated Output 2
|
||||
FUNC_UART3_OUT1 FPIOAFunction = 184 // UART3 User-designated Output 1
|
||||
FUNC_UART3_SIR_OUT FPIOAFunction = 185 // UART3 Serial Infrared Output
|
||||
FUNC_UART3_BAUD FPIOAFunction = 186 // UART3 Transmit Clock Output
|
||||
FUNC_UART3_RE FPIOAFunction = 187 // UART3 Receiver Output Enable
|
||||
FUNC_UART3_DE FPIOAFunction = 188 // UART3 Driver Output Enable
|
||||
FUNC_UART3_RS485_EN FPIOAFunction = 189 // UART3 RS485 Enable
|
||||
FUNC_TIMER0_TOGGLE1 FPIOAFunction = 190 // TIMER0 Toggle Output 1
|
||||
FUNC_TIMER0_TOGGLE2 FPIOAFunction = 191 // TIMER0 Toggle Output 2
|
||||
FUNC_TIMER0_TOGGLE3 FPIOAFunction = 192 // TIMER0 Toggle Output 3
|
||||
FUNC_TIMER0_TOGGLE4 FPIOAFunction = 193 // TIMER0 Toggle Output 4
|
||||
FUNC_TIMER1_TOGGLE1 FPIOAFunction = 194 // TIMER1 Toggle Output 1
|
||||
FUNC_TIMER1_TOGGLE2 FPIOAFunction = 195 // TIMER1 Toggle Output 2
|
||||
FUNC_TIMER1_TOGGLE3 FPIOAFunction = 196 // TIMER1 Toggle Output 3
|
||||
FUNC_TIMER1_TOGGLE4 FPIOAFunction = 197 // TIMER1 Toggle Output 4
|
||||
FUNC_TIMER2_TOGGLE1 FPIOAFunction = 198 // TIMER2 Toggle Output 1
|
||||
FUNC_TIMER2_TOGGLE2 FPIOAFunction = 199 // TIMER2 Toggle Output 2
|
||||
FUNC_TIMER2_TOGGLE3 FPIOAFunction = 200 // TIMER2 Toggle Output 3
|
||||
FUNC_TIMER2_TOGGLE4 FPIOAFunction = 201 // TIMER2 Toggle Output 4
|
||||
FUNC_CLK_SPI2 FPIOAFunction = 202 // Clock SPI2
|
||||
FUNC_CLK_I2C2 FPIOAFunction = 203 // Clock I2C2
|
||||
FUNC_INTERNAL0 FPIOAFunction = 204 // Internal function signal 0
|
||||
FUNC_INTERNAL1 FPIOAFunction = 205 // Internal function signal 1
|
||||
FUNC_INTERNAL2 FPIOAFunction = 206 // Internal function signal 2
|
||||
FUNC_INTERNAL3 FPIOAFunction = 207 // Internal function signal 3
|
||||
FUNC_INTERNAL4 FPIOAFunction = 208 // Internal function signal 4
|
||||
FUNC_INTERNAL5 FPIOAFunction = 209 // Internal function signal 5
|
||||
FUNC_INTERNAL6 FPIOAFunction = 210 // Internal function signal 6
|
||||
FUNC_INTERNAL7 FPIOAFunction = 211 // Internal function signal 7
|
||||
FUNC_INTERNAL8 FPIOAFunction = 212 // Internal function signal 8
|
||||
FUNC_INTERNAL9 FPIOAFunction = 213 // Internal function signal 9
|
||||
FUNC_INTERNAL10 FPIOAFunction = 214 // Internal function signal 10
|
||||
FUNC_INTERNAL11 FPIOAFunction = 215 // Internal function signal 11
|
||||
FUNC_INTERNAL12 FPIOAFunction = 216 // Internal function signal 12
|
||||
FUNC_INTERNAL13 FPIOAFunction = 217 // Internal function signal 13
|
||||
FUNC_INTERNAL14 FPIOAFunction = 218 // Internal function signal 14
|
||||
FUNC_INTERNAL15 FPIOAFunction = 219 // Internal function signal 15
|
||||
FUNC_INTERNAL16 FPIOAFunction = 220 // Internal function signal 16
|
||||
FUNC_INTERNAL17 FPIOAFunction = 221 // Internal function signal 17
|
||||
FUNC_CONSTANT FPIOAFunction = 222 // Constant function
|
||||
FUNC_INTERNAL18 FPIOAFunction = 223 // Internal function signal 18
|
||||
FUNC_DEBUG0 FPIOAFunction = 224 // Debug function 0
|
||||
FUNC_DEBUG1 FPIOAFunction = 225 // Debug function 1
|
||||
FUNC_DEBUG2 FPIOAFunction = 226 // Debug function 2
|
||||
FUNC_DEBUG3 FPIOAFunction = 227 // Debug function 3
|
||||
FUNC_DEBUG4 FPIOAFunction = 228 // Debug function 4
|
||||
FUNC_DEBUG5 FPIOAFunction = 229 // Debug function 5
|
||||
FUNC_DEBUG6 FPIOAFunction = 230 // Debug function 6
|
||||
FUNC_DEBUG7 FPIOAFunction = 231 // Debug function 7
|
||||
FUNC_DEBUG8 FPIOAFunction = 232 // Debug function 8
|
||||
FUNC_DEBUG9 FPIOAFunction = 233 // Debug function 9
|
||||
FUNC_DEBUG10 FPIOAFunction = 234 // Debug function 10
|
||||
FUNC_DEBUG11 FPIOAFunction = 235 // Debug function 11
|
||||
FUNC_DEBUG12 FPIOAFunction = 236 // Debug function 12
|
||||
FUNC_DEBUG13 FPIOAFunction = 237 // Debug function 13
|
||||
FUNC_DEBUG14 FPIOAFunction = 238 // Debug function 14
|
||||
FUNC_DEBUG15 FPIOAFunction = 239 // Debug function 15
|
||||
FUNC_DEBUG16 FPIOAFunction = 240 // Debug function 16
|
||||
FUNC_DEBUG17 FPIOAFunction = 241 // Debug function 17
|
||||
FUNC_DEBUG18 FPIOAFunction = 242 // Debug function 18
|
||||
FUNC_DEBUG19 FPIOAFunction = 243 // Debug function 19
|
||||
FUNC_DEBUG20 FPIOAFunction = 244 // Debug function 20
|
||||
FUNC_DEBUG21 FPIOAFunction = 245 // Debug function 21
|
||||
FUNC_DEBUG22 FPIOAFunction = 246 // Debug function 22
|
||||
FUNC_DEBUG23 FPIOAFunction = 247 // Debug function 23
|
||||
FUNC_DEBUG24 FPIOAFunction = 248 // Debug function 24
|
||||
FUNC_DEBUG25 FPIOAFunction = 249 // Debug function 25
|
||||
FUNC_DEBUG26 FPIOAFunction = 250 // Debug function 26
|
||||
FUNC_DEBUG27 FPIOAFunction = 251 // Debug function 27
|
||||
FUNC_DEBUG28 FPIOAFunction = 252 // Debug function 28
|
||||
FUNC_DEBUG29 FPIOAFunction = 253 // Debug function 29
|
||||
FUNC_DEBUG30 FPIOAFunction = 254 // Debug function 30
|
||||
FUNC_DEBUG31 FPIOAFunction = 255 // Debug function 31
|
||||
)
|
||||
|
||||
// These are the default FPIOA values for each function.
|
||||
// (source: https://github.com/kendryte/kendryte-standalone-sdk/blob/develop/lib/drivers/fpioa.c#L69)
|
||||
var fpioaFuncDefaults [256]uint32 = [256]uint32{
|
||||
0x00900000, 0x00900001, 0x00900002, 0x00001f03, 0x00b03f04, 0x00b03f05, 0x00b03f06, 0x00b03f07, 0x00b03f08,
|
||||
0x00b03f09, 0x00b03f0a, 0x00b03f0b, 0x00001f0c, 0x00001f0d, 0x00001f0e, 0x00001f0f, 0x03900010, 0x00001f11,
|
||||
0x00900012, 0x00001f13, 0x00900014, 0x00900015, 0x00001f16, 0x00001f17, 0x00901f18, 0x00901f19, 0x00901f1a,
|
||||
0x00901f1b, 0x00901f1c, 0x00901f1d, 0x00901f1e, 0x00901f1f, 0x00901f20, 0x00901f21, 0x00901f22, 0x00901f23,
|
||||
0x00901f24, 0x00901f25, 0x00901f26, 0x00901f27, 0x00901f28, 0x00901f29, 0x00901f2a, 0x00901f2b, 0x00901f2c,
|
||||
0x00901f2d, 0x00901f2e, 0x00901f2f, 0x00901f30, 0x00901f31, 0x00901f32, 0x00901f33, 0x00901f34, 0x00901f35,
|
||||
0x00901f36, 0x00901f37, 0x00901f38, 0x00901f39, 0x00901f3a, 0x00901f3b, 0x00901f3c, 0x00901f3d, 0x00901f3e,
|
||||
0x00901f3f, 0x00900040, 0x00001f41, 0x00900042, 0x00001f43, 0x00900044, 0x00001f45, 0x00b03f46, 0x00b03f47,
|
||||
0x00b03f48, 0x00b03f49, 0x00b03f4a, 0x00b03f4b, 0x00b03f4c, 0x00b03f4d, 0x00001f4e, 0x00001f4f, 0x00001f50,
|
||||
0x00001f51, 0x03900052, 0x00001f53, 0x00b03f54, 0x00900055, 0x00900056, 0x00001f57, 0x00001f58, 0x00001f59,
|
||||
0x0090005a, 0x0090005b, 0x0090005c, 0x0090005d, 0x00001f5e, 0x00001f5f, 0x00001f60, 0x00001f61, 0x00001f62,
|
||||
0x00001f63, 0x00001f64, 0x00900065, 0x00900066, 0x00900067, 0x00900068, 0x00001f69, 0x00001f6a, 0x00001f6b,
|
||||
0x00001f6c, 0x00001f6d, 0x00001f6e, 0x00001f6f, 0x00900070, 0x00900071, 0x00900072, 0x00900073, 0x00001f74,
|
||||
0x00001f75, 0x00001f76, 0x00001f77, 0x00000078, 0x00000079, 0x0000007a, 0x0000007b, 0x0000007c, 0x0000007d,
|
||||
0x0099107e, 0x0099107f, 0x00991080, 0x00991081, 0x00991082, 0x00991083, 0x00001f84, 0x00001f85, 0x00001f86,
|
||||
0x00900087, 0x00900088, 0x00900089, 0x0090008a, 0x0090008b, 0x0090008c, 0x0090008d, 0x0090008e, 0x0090008f,
|
||||
0x00900090, 0x00900091, 0x00993092, 0x00993093, 0x00900094, 0x00900095, 0x00900096, 0x00900097, 0x00900098,
|
||||
0x00001f99, 0x00001f9a, 0x00001f9b, 0x00001f9c, 0x00001f9d, 0x00001f9e, 0x00001f9f, 0x00001fa0, 0x00001fa1,
|
||||
0x009000a2, 0x009000a3, 0x009000a4, 0x009000a5, 0x009000a6, 0x00001fa7, 0x00001fa8, 0x00001fa9, 0x00001faa,
|
||||
0x00001fab, 0x00001fac, 0x00001fad, 0x00001fae, 0x00001faf, 0x009000b0, 0x009000b1, 0x009000b2, 0x009000b3,
|
||||
0x009000b4, 0x00001fb5, 0x00001fb6, 0x00001fb7, 0x00001fb8, 0x00001fb9, 0x00001fba, 0x00001fbb, 0x00001fbc,
|
||||
0x00001fbd, 0x00001fbe, 0x00001fbf, 0x00001fc0, 0x00001fc1, 0x00001fc2, 0x00001fc3, 0x00001fc4, 0x00001fc5,
|
||||
0x00001fc6, 0x00001fc7, 0x00001fc8, 0x00001fc9, 0x00001fca, 0x00001fcb, 0x00001fcc, 0x00001fcd, 0x00001fce,
|
||||
0x00001fcf, 0x00001fd0, 0x00001fd1, 0x00001fd2, 0x00001fd3, 0x00001fd4, 0x009000d5, 0x009000d6, 0x009000d7,
|
||||
0x009000d8, 0x009100d9, 0x00991fda, 0x009000db, 0x009000dc, 0x009000dd, 0x000000de, 0x009000df, 0x00001fe0,
|
||||
0x00001fe1, 0x00001fe2, 0x00001fe3, 0x00001fe4, 0x00001fe5, 0x00001fe6, 0x00001fe7, 0x00001fe8, 0x00001fe9,
|
||||
0x00001fea, 0x00001feb, 0x00001fec, 0x00001fed, 0x00001fee, 0x00001fef, 0x00001ff0, 0x00001ff1, 0x00001ff2,
|
||||
0x00001ff3, 0x00001ff4, 0x00001ff5, 0x00001ff6, 0x00001ff7, 0x00001ff8, 0x00001ff9, 0x00001ffa, 0x00001ffb,
|
||||
0x00001ffc, 0x00001ffd, 0x00001ffe, 0x00001fff,
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
// +build maixbit
|
||||
|
||||
package machine
|
||||
|
||||
// Pins on the MAix Bit.
|
||||
const (
|
||||
D0 = P00 // JTAG_TCLK
|
||||
D1 = P01 // JTAG_TDI
|
||||
D2 = P02 // JTAG_TMS
|
||||
D3 = P03 // JTAG_TDO
|
||||
D4 = P04 // UARTHS_RX
|
||||
D5 = P05 // UARTHS_TX
|
||||
D6 = P06 // RESV0
|
||||
D7 = P07 // RESV0
|
||||
D8 = P08 // GPIO1
|
||||
D9 = P09 // GPIO2
|
||||
D10 = P10 // GPIO3
|
||||
D11 = P11 // GPIO4
|
||||
D12 = P12 // GPIO5
|
||||
D13 = P13 // GPIO6
|
||||
D14 = P14 // GPIO7
|
||||
D15 = P15 // GPIO8
|
||||
D16 = P16 // GPIOHS0
|
||||
D17 = P17 // GPIOHS1
|
||||
D18 = P18 // GPIOHS2
|
||||
D19 = P19 // GPIOHS3
|
||||
D20 = P20 // GPIOHS4
|
||||
D21 = P21 // GPIOHS5
|
||||
D22 = P22 // GPIOHS6
|
||||
D23 = P23 // GPIOHS7
|
||||
D24 = P24 // GPIOHS8
|
||||
D25 = P25 // GPIOHS9
|
||||
D26 = P26 // GPIOHS10 / SPI0_SDI
|
||||
D27 = P27 // GPIOHS11 / SPI0_SCLK
|
||||
D28 = P28 // GPIOHS12 / SPI0_SDO
|
||||
D29 = P29 // GPIOHS13
|
||||
D30 = P30 // GPIOHS14
|
||||
D31 = P31 // GPIOHS15
|
||||
D32 = P32 // GPIOHS16
|
||||
D33 = P33 // GPIOHS17
|
||||
D34 = P34 // GPIOHS18
|
||||
D35 = P35 // GPIOHS19
|
||||
)
|
||||
|
||||
const (
|
||||
LED = LED1
|
||||
LED1 = LED_RED
|
||||
LED2 = LED_GREEN
|
||||
LED3 = LED_BLUE
|
||||
LED_RED = D13
|
||||
LED_GREEN = D12
|
||||
LED_BLUE = D14
|
||||
)
|
||||
|
||||
// Default pins for UARTHS.
|
||||
const (
|
||||
UART_TX_PIN = D5
|
||||
UART_RX_PIN = D4
|
||||
)
|
||||
|
||||
// SPI pins.
|
||||
const (
|
||||
SPI0_SCK_PIN = D27
|
||||
SPI0_SDO_PIN = D28
|
||||
SPI0_SDI_PIN = D26
|
||||
)
|
||||
|
||||
// I2C pins.
|
||||
const (
|
||||
I2C0_SDA_PIN = D34
|
||||
I2C0_SCL_PIN = D35
|
||||
)
|
||||
@@ -0,0 +1,28 @@
|
||||
// +build k210,maixbit
|
||||
|
||||
package machine
|
||||
|
||||
import "device/kendryte"
|
||||
|
||||
// SPI on the MAix Bit.
|
||||
var (
|
||||
SPI0 = SPI{
|
||||
Bus: kendryte.SPI0,
|
||||
}
|
||||
SPI1 = SPI{
|
||||
Bus: kendryte.SPI1,
|
||||
}
|
||||
)
|
||||
|
||||
// I2C on the MAix Bit.
|
||||
var (
|
||||
I2C0 = I2C{
|
||||
Bus: kendryte.I2C0,
|
||||
}
|
||||
I2C1 = I2C{
|
||||
Bus: kendryte.I2C1,
|
||||
}
|
||||
I2C2 = I2C{
|
||||
Bus: kendryte.I2C2,
|
||||
}
|
||||
)
|
||||
@@ -75,19 +75,19 @@ const (
|
||||
|
||||
// SPI pins
|
||||
const (
|
||||
SPI0_SCK_PIN = PA13 // SCK: SERCOM2/PAD[1]
|
||||
SPI0_MOSI_PIN = PA12 // MOSI: SERCOM2/PAD[0]
|
||||
SPI0_MISO_PIN = PA14 // MISO: SERCOM2/PAD[2]
|
||||
SPI0_SCK_PIN = PA13 // SCK: SERCOM2/PAD[1]
|
||||
SPI0_SDO_PIN = PA12 // SDO: SERCOM2/PAD[0]
|
||||
SPI0_SDI_PIN = PA14 // SDI: SERCOM2/PAD[2]
|
||||
|
||||
NINA_MOSI = SPI0_MOSI_PIN
|
||||
NINA_MISO = SPI0_MISO_PIN
|
||||
NINA_SCK = SPI0_SCK_PIN
|
||||
NINA_SDO = SPI0_SDO_PIN
|
||||
NINA_SDI = SPI0_SDI_PIN
|
||||
NINA_SCK = SPI0_SCK_PIN
|
||||
)
|
||||
|
||||
const (
|
||||
SPI1_SCK_PIN = D12 // MISO: SERCOM1/PAD[1]
|
||||
SPI1_MOSI_PIN = D11 // MOSI: SERCOM1/PAD[3]
|
||||
SPI1_MISO_PIN = D13 // SCK: SERCOM1/PAD[0]
|
||||
SPI1_SCK_PIN = D12 // SDI: SERCOM1/PAD[1]
|
||||
SPI1_SDO_PIN = D11 // SDO: SERCOM1/PAD[3]
|
||||
SPI1_SDI_PIN = D13 // SCK: SERCOM1/PAD[0]
|
||||
)
|
||||
|
||||
// USB CDC identifiers
|
||||
|
||||
@@ -33,9 +33,9 @@ const (
|
||||
|
||||
// SPI pins
|
||||
const (
|
||||
SPI0_SCK_PIN Pin = 23 // P13 on the board
|
||||
SPI0_MOSI_PIN Pin = 21 // P15 on the board
|
||||
SPI0_MISO_PIN Pin = 22 // P14 on the board
|
||||
SPI0_SCK_PIN Pin = 23 // P13 on the board
|
||||
SPI0_SDO_PIN Pin = 21 // P15 on the board
|
||||
SPI0_SDI_PIN Pin = 22 // P14 on the board
|
||||
)
|
||||
|
||||
// GPIO/Analog pins
|
||||
|
||||
@@ -31,9 +31,9 @@ const (
|
||||
|
||||
// SPI pins (unused)
|
||||
const (
|
||||
SPI0_SCK_PIN = NoPin
|
||||
SPI0_MOSI_PIN = NoPin
|
||||
SPI0_MISO_PIN = NoPin
|
||||
SPI0_SCK_PIN = NoPin
|
||||
SPI0_SDO_PIN = NoPin
|
||||
SPI0_SDI_PIN = NoPin
|
||||
)
|
||||
|
||||
// USB CDC identifiers
|
||||
|
||||
@@ -113,9 +113,9 @@ func init() {
|
||||
|
||||
// SPI pins
|
||||
const (
|
||||
SPI0_SCK_PIN = PA5
|
||||
SPI0_MISO_PIN = PA6
|
||||
SPI0_MOSI_PIN = PA7
|
||||
SPI0_SCK_PIN = PA5
|
||||
SPI0_SDI_PIN = PA6
|
||||
SPI0_SDO_PIN = PA7
|
||||
)
|
||||
|
||||
// I2C pins
|
||||
|
||||
@@ -34,8 +34,8 @@ const (
|
||||
D8 Pin = 35
|
||||
D9 Pin = 6 // Also TX
|
||||
D10 Pin = 8 // Also RX
|
||||
D11 Pin = 46 // Also MISO
|
||||
D12 Pin = 45 // Also MOSI
|
||||
D11 Pin = 46 // Also SDI
|
||||
D12 Pin = 45 // Also SDO
|
||||
D13 Pin = 47 // Also SCK
|
||||
)
|
||||
|
||||
@@ -58,16 +58,16 @@ const (
|
||||
|
||||
// SPI pins
|
||||
const (
|
||||
SPI0_SCK_PIN Pin = 47
|
||||
SPI0_MOSI_PIN Pin = 45
|
||||
SPI0_MISO_PIN Pin = 46
|
||||
SPI0_SCK_PIN Pin = 47
|
||||
SPI0_SDO_PIN Pin = 45
|
||||
SPI0_SDI_PIN Pin = 46
|
||||
)
|
||||
|
||||
// Internal 4MB SPI Flash
|
||||
const (
|
||||
SPI1_SCK_PIN Pin = 19
|
||||
SPI1_MOSI_PIN Pin = 20
|
||||
SPI1_MISO_PIN Pin = 21
|
||||
SPI1_SDO_PIN Pin = 20
|
||||
SPI1_SDI_PIN Pin = 21
|
||||
SPI1_CS_PIN Pin = 17
|
||||
SPI1_WP_PIN Pin = 22
|
||||
SPI1_HOLD_PIN Pin = 23
|
||||
|
||||
@@ -34,8 +34,8 @@ const (
|
||||
D8 Pin = 35
|
||||
D9 Pin = 6 // Also TX
|
||||
D10 Pin = 8 // Also RX
|
||||
D11 Pin = 46 // Also MISO
|
||||
D12 Pin = 45 // Also MOSI
|
||||
D11 Pin = 46 // Also SDI
|
||||
D12 Pin = 45 // Also SDO
|
||||
D13 Pin = 47 // Also SCK
|
||||
)
|
||||
|
||||
@@ -63,16 +63,16 @@ const (
|
||||
|
||||
// SPI pins
|
||||
const (
|
||||
SPI0_SCK_PIN Pin = 47
|
||||
SPI0_MOSI_PIN Pin = 45
|
||||
SPI0_MISO_PIN Pin = 46
|
||||
SPI0_SCK_PIN Pin = 47
|
||||
SPI0_SDO_PIN Pin = 45
|
||||
SPI0_SDI_PIN Pin = 46
|
||||
)
|
||||
|
||||
// Internal 4MB SPI Flash
|
||||
const (
|
||||
SPI1_SCK_PIN Pin = 19
|
||||
SPI1_MOSI_PIN Pin = 20
|
||||
SPI1_MISO_PIN Pin = 21
|
||||
SPI1_SDO_PIN Pin = 20
|
||||
SPI1_SDI_PIN Pin = 21
|
||||
SPI1_CS_PIN Pin = 17
|
||||
SPI1_WP_PIN Pin = 22
|
||||
SPI1_HOLD_PIN Pin = 23
|
||||
|
||||
@@ -34,8 +34,8 @@ const (
|
||||
D8 Pin = 35
|
||||
D9 Pin = 6 // Also TX
|
||||
D10 Pin = 8 // Also RX
|
||||
D11 Pin = 46 // Also MISO
|
||||
D12 Pin = 45 // Also MOSI
|
||||
D11 Pin = 46 // Also SDI
|
||||
D12 Pin = 45 // Also SDO
|
||||
D13 Pin = 47 // Also SCK
|
||||
)
|
||||
|
||||
@@ -58,16 +58,16 @@ const (
|
||||
|
||||
// SPI pins
|
||||
const (
|
||||
SPI0_SCK_PIN Pin = 47
|
||||
SPI0_MOSI_PIN Pin = 45
|
||||
SPI0_MISO_PIN Pin = 46
|
||||
SPI0_SCK_PIN Pin = 47
|
||||
SPI0_SDO_PIN Pin = 45
|
||||
SPI0_SDI_PIN Pin = 46
|
||||
)
|
||||
|
||||
// Internal 4MB SPI Flash
|
||||
const (
|
||||
SPI1_SCK_PIN Pin = 19
|
||||
SPI1_MOSI_PIN Pin = 20
|
||||
SPI1_MISO_PIN Pin = 21
|
||||
SPI1_SDO_PIN Pin = 20
|
||||
SPI1_SDI_PIN Pin = 21
|
||||
SPI1_CS_PIN Pin = 17
|
||||
SPI1_WP_PIN Pin = 22
|
||||
SPI1_HOLD_PIN Pin = 23
|
||||
|
||||
@@ -33,7 +33,7 @@ const (
|
||||
|
||||
// SPI pins (unused)
|
||||
const (
|
||||
SPI0_SCK_PIN = NoPin
|
||||
SPI0_MOSI_PIN = NoPin
|
||||
SPI0_MISO_PIN = NoPin
|
||||
SPI0_SCK_PIN = NoPin
|
||||
SPI0_SDO_PIN = NoPin
|
||||
SPI0_SDI_PIN = NoPin
|
||||
)
|
||||
|
||||
@@ -47,7 +47,7 @@ const (
|
||||
|
||||
// SPI pins
|
||||
const (
|
||||
SPI0_SCK_PIN Pin = 25
|
||||
SPI0_MOSI_PIN Pin = 23
|
||||
SPI0_MISO_PIN Pin = 24
|
||||
SPI0_SCK_PIN Pin = 25
|
||||
SPI0_SDO_PIN Pin = 23
|
||||
SPI0_SDI_PIN Pin = 24
|
||||
)
|
||||
|
||||
@@ -46,9 +46,9 @@ const (
|
||||
|
||||
// SPI pins
|
||||
const (
|
||||
SPI0_SCK_PIN Pin = 47 // P1.15
|
||||
SPI0_MOSI_PIN Pin = 45 // P1.13
|
||||
SPI0_MISO_PIN Pin = 46 // P1.14
|
||||
SPI0_SCK_PIN Pin = 47 // P1.15
|
||||
SPI0_SDO_PIN Pin = 45 // P1.13
|
||||
SPI0_SDI_PIN Pin = 46 // P1.14
|
||||
)
|
||||
|
||||
// USB CDC identifiers
|
||||
|
||||
@@ -27,9 +27,9 @@ const (
|
||||
|
||||
// SPI pins for the PineTime.
|
||||
const (
|
||||
SPI0_SCK_PIN Pin = 2
|
||||
SPI0_MOSI_PIN Pin = 3
|
||||
SPI0_MISO_PIN Pin = 4
|
||||
SPI0_SCK_PIN Pin = 2
|
||||
SPI0_SDO_PIN Pin = 3
|
||||
SPI0_SDI_PIN Pin = 4
|
||||
)
|
||||
|
||||
// I2C pins for the PineTime.
|
||||
@@ -51,7 +51,7 @@ const VIBRATOR_PIN Pin = 16
|
||||
// http://files.pine64.org/doc/PineTime/PineTime%20Port%20Assignment%20rev1.0.pdf
|
||||
const (
|
||||
LCD_SCK = SPI0_SCK_PIN
|
||||
LCD_SDI = SPI0_MOSI_PIN
|
||||
LCD_SDI = SPI0_SDO_PIN
|
||||
LCD_RS Pin = 18
|
||||
LCD_CS Pin = 25
|
||||
LCD_RESET Pin = 26
|
||||
|
||||
@@ -91,16 +91,16 @@ const (
|
||||
|
||||
// SPI pins
|
||||
const (
|
||||
SPI0_SCK_PIN = PA17 // SCK: SERCOM1/PAD[1]
|
||||
SPI0_MOSI_PIN = PB23 // MOSI: SERCOM1/PAD[3]
|
||||
SPI0_MISO_PIN = PB22 // MISO: SERCOM1/PAD[2]
|
||||
SPI0_SCK_PIN = PA17 // SCK: SERCOM1/PAD[1]
|
||||
SPI0_SDO_PIN = PB23 // SDO: SERCOM1/PAD[3]
|
||||
SPI0_SDI_PIN = PB22 // SDI: SERCOM1/PAD[2]
|
||||
)
|
||||
|
||||
// TFT SPI pins
|
||||
const (
|
||||
SPI1_SCK_PIN = PB13 // SCK: SERCOM4/PAD[1]
|
||||
SPI1_MOSI_PIN = PB15 // MOSI: SERCOM4/PAD[3]
|
||||
SPI1_MISO_PIN = NoPin
|
||||
SPI1_SCK_PIN = PB13 // SCK: SERCOM4/PAD[1]
|
||||
SPI1_SDO_PIN = PB15 // SDO: SERCOM4/PAD[3]
|
||||
SPI1_SDI_PIN = NoPin
|
||||
)
|
||||
|
||||
// USB CDC identifiers
|
||||
|
||||
@@ -107,9 +107,9 @@ var (
|
||||
|
||||
// SPI pins
|
||||
const (
|
||||
SPI0_SCK_PIN = PA17 // SCK: SERCOM1/PAD[1]
|
||||
SPI0_MOSI_PIN = PB23 // MOSI: SERCOM1/PAD[3]
|
||||
SPI0_MISO_PIN = PB22 // MISO: SERCOM1/PAD[2]
|
||||
SPI0_SCK_PIN = PA17 // SCK: SERCOM1/PAD[1]
|
||||
SPI0_SDO_PIN = PB23 // SDO: SERCOM1/PAD[3]
|
||||
SPI0_SDI_PIN = PB22 // SDI: SERCOM1/PAD[2]
|
||||
)
|
||||
|
||||
// SPI on the PyGamer.
|
||||
@@ -122,9 +122,9 @@ var (
|
||||
|
||||
// TFT SPI pins
|
||||
const (
|
||||
SPI1_SCK_PIN = PB13 // SCK: SERCOM4/PAD[1]
|
||||
SPI1_MOSI_PIN = PB15 // MOSI: SERCOM4/PAD[3]
|
||||
SPI1_MISO_PIN = NoPin
|
||||
SPI1_SCK_PIN = PB13 // SCK: SERCOM4/PAD[1]
|
||||
SPI1_SDO_PIN = PB15 // SDO: SERCOM4/PAD[3]
|
||||
SPI1_SDI_PIN = NoPin
|
||||
)
|
||||
|
||||
// TFT SPI on the PyGamer.
|
||||
|
||||
@@ -26,9 +26,9 @@ const (
|
||||
D26 = PB09 // TFT_WR
|
||||
D27 = PB02 // SDA
|
||||
D28 = PB03 // SCL
|
||||
D29 = PA12 // MOSI
|
||||
D29 = PA12 // SDO
|
||||
D30 = PA13 // SCK
|
||||
D31 = PA14 // MISO
|
||||
D31 = PA14 // SDI
|
||||
D32 = PB30 // SD_CS
|
||||
D33 = PA01 // SD_CARD_DETECT
|
||||
D34 = PA16 // LCD_DATA0
|
||||
@@ -114,13 +114,13 @@ const (
|
||||
|
||||
// SPI pins
|
||||
const (
|
||||
SPI0_SCK_PIN = PA13 // SCK: SERCOM1/PAD[1]
|
||||
SPI0_MOSI_PIN = PA12 // MOSI: SERCOM1/PAD[3]
|
||||
SPI0_MISO_PIN = PA14 // MISO: SERCOM1/PAD[2]
|
||||
SPI0_SCK_PIN = PA13 // SCK: SERCOM1/PAD[1]
|
||||
SPI0_SDO_PIN = PA12 // SDO: SERCOM1/PAD[3]
|
||||
SPI0_SDI_PIN = PA14 // SDI: SERCOM1/PAD[2]
|
||||
|
||||
NINA_MOSI = SPI0_MOSI_PIN
|
||||
NINA_MISO = SPI0_MISO_PIN
|
||||
NINA_SCK = SPI0_SCK_PIN
|
||||
NINA_SDO = SPI0_SDO_PIN
|
||||
NINA_SDI = SPI0_SDI_PIN
|
||||
NINA_SCK = SPI0_SCK_PIN
|
||||
)
|
||||
|
||||
// USB CDC identifiers
|
||||
|
||||
@@ -20,7 +20,7 @@ const (
|
||||
EPD_DC_PIN Pin = 16
|
||||
EPD_CS_PIN Pin = 17
|
||||
EPD_SCK_PIN Pin = 19
|
||||
EPD_MOSI_PIN Pin = 20
|
||||
EPD_SDO_PIN Pin = 20
|
||||
POWER_SUPPLY_PIN Pin = 32
|
||||
)
|
||||
|
||||
@@ -43,9 +43,9 @@ const (
|
||||
|
||||
// SPI pins
|
||||
const (
|
||||
SPI0_SCK_PIN Pin = 47
|
||||
SPI0_MOSI_PIN Pin = 45
|
||||
SPI0_MISO_PIN Pin = 46
|
||||
SPI0_SCK_PIN Pin = 47
|
||||
SPI0_SDO_PIN Pin = 45
|
||||
SPI0_SDI_PIN Pin = 46
|
||||
)
|
||||
|
||||
// PowerSupplyActive enables the supply voltages for nRF52840 and peripherals (true) or only for nRF52840 (false)
|
||||
|
||||
@@ -132,12 +132,12 @@ func init() {
|
||||
|
||||
// SPI pins
|
||||
const (
|
||||
SPI1_SCK_PIN = PA5
|
||||
SPI1_MISO_PIN = PA6
|
||||
SPI1_MOSI_PIN = PA7
|
||||
SPI0_SCK_PIN = SPI1_SCK_PIN
|
||||
SPI0_MISO_PIN = SPI1_MISO_PIN
|
||||
SPI0_MOSI_PIN = SPI1_MOSI_PIN
|
||||
SPI1_SCK_PIN = PA5
|
||||
SPI1_SDI_PIN = PA6
|
||||
SPI1_SDO_PIN = PA7
|
||||
SPI0_SCK_PIN = SPI1_SCK_PIN
|
||||
SPI0_SDI_PIN = SPI1_SDI_PIN
|
||||
SPI0_SDO_PIN = SPI1_SDO_PIN
|
||||
)
|
||||
|
||||
// MEMs accelerometer
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
// +build nxp,mk66f18,teensy36
|
||||
|
||||
package machine
|
||||
|
||||
// CPUFrequency returns the frequency of the ARM core clock (180MHz)
|
||||
func CPUFrequency() uint32 { return 180000000 }
|
||||
|
||||
// ClockFrequency returns the frequency of the external oscillator (16MHz)
|
||||
func ClockFrequency() uint32 { return 16000000 }
|
||||
|
||||
// LED on the Teensy
|
||||
const LED = PC05
|
||||
|
||||
// digital IO
|
||||
const (
|
||||
D00 = PB16
|
||||
D01 = PB17
|
||||
D02 = PD00
|
||||
D03 = PA12
|
||||
D04 = PA13
|
||||
D05 = PD07
|
||||
D06 = PD04
|
||||
D07 = PD02
|
||||
D08 = PD03
|
||||
D09 = PC03
|
||||
D10 = PC04
|
||||
D11 = PC06
|
||||
D12 = PC07
|
||||
D13 = PC05
|
||||
D14 = PD01
|
||||
D15 = PC00
|
||||
D16 = PB00
|
||||
D17 = PB01
|
||||
D18 = PB03
|
||||
D19 = PB02
|
||||
D20 = PD05
|
||||
D21 = PD06
|
||||
D22 = PC01
|
||||
D23 = PC02
|
||||
D24 = PE26
|
||||
D25 = PA05
|
||||
D26 = PA14
|
||||
D27 = PA15
|
||||
D28 = PA16
|
||||
D29 = PB18
|
||||
D30 = PB19
|
||||
D31 = PB10
|
||||
D32 = PB11
|
||||
D33 = PE24
|
||||
D34 = PE25
|
||||
D35 = PC08
|
||||
D36 = PC09
|
||||
D37 = PC10
|
||||
D38 = PC11
|
||||
D39 = PA17
|
||||
D40 = PA28
|
||||
D41 = PA29
|
||||
D42 = PA26
|
||||
D43 = PB20
|
||||
D44 = PB22
|
||||
D45 = PB23
|
||||
D46 = PB21
|
||||
D47 = PD08
|
||||
D48 = PD09
|
||||
D49 = PB04
|
||||
D50 = PB05
|
||||
D51 = PD14
|
||||
D52 = PD13
|
||||
D53 = PD12
|
||||
D54 = PD15
|
||||
D55 = PD11
|
||||
D56 = PE10
|
||||
D57 = PE11
|
||||
D58 = PE00
|
||||
D59 = PE01
|
||||
D60 = PE02
|
||||
D61 = PE03
|
||||
D62 = PE04
|
||||
D63 = PE05
|
||||
)
|
||||
|
||||
var (
|
||||
TeensyUART1 = &UART0
|
||||
TeensyUART2 = &UART1
|
||||
TeensyUART3 = &UART2
|
||||
TeensyUART4 = &UART3
|
||||
TeensyUART5 = &UART4
|
||||
)
|
||||
|
||||
const (
|
||||
defaultUART0RX = D00
|
||||
defaultUART0TX = D01
|
||||
defaultUART1RX = D09
|
||||
defaultUART1TX = D10
|
||||
defaultUART2RX = D07
|
||||
defaultUART2TX = D08
|
||||
defaultUART3RX = D31
|
||||
defaultUART3TX = D32
|
||||
defaultUART4RX = D34
|
||||
defaultUART4TX = D33
|
||||
)
|
||||
@@ -60,9 +60,9 @@ func init() {
|
||||
|
||||
// SPI pins
|
||||
const (
|
||||
SPI0_SCK_PIN = D3
|
||||
SPI0_MOSI_PIN = D4
|
||||
SPI0_MISO_PIN = D2
|
||||
SPI0_SCK_PIN = D3
|
||||
SPI0_SDO_PIN = D4
|
||||
SPI0_SDI_PIN = D2
|
||||
)
|
||||
|
||||
// SPI on the Trinket M0.
|
||||
|
||||
@@ -86,8 +86,8 @@ const (
|
||||
BCM6 = PB13 // GCLK
|
||||
BCM7 = PA05 // DAC1
|
||||
BCM8 = PB01 // SPI SS
|
||||
BCM9 = PB00 // SPI MISO
|
||||
BCM10 = PB02 // SPI MOSI
|
||||
BCM9 = PB00 // SPI SDI
|
||||
BCM10 = PB02 // SPI SDO
|
||||
BCM11 = PB03 // SPI SCK
|
||||
BCM12 = PB06
|
||||
BCM13 = PA07
|
||||
@@ -132,9 +132,6 @@ const (
|
||||
PIN_DAC0 = PA02
|
||||
PIN_DAC1 = PA05
|
||||
|
||||
DAC0 = PIN_DAC0
|
||||
DAC1 = PIN_DAC1
|
||||
|
||||
// FPO Analog RPIs
|
||||
//FPC_A7 = FPC_D7
|
||||
//FPC_A8 = FPC_D8
|
||||
@@ -219,58 +216,58 @@ const (
|
||||
WIO_LIS3DH_INT = PC21
|
||||
|
||||
// SPI
|
||||
PIN_SPI_MISO = PB00
|
||||
PIN_SPI_MOSI = PB02
|
||||
PIN_SPI_SCK = PB03
|
||||
PIN_SPI_SS = PB01
|
||||
PIN_SPI_SDI = PB00
|
||||
PIN_SPI_SDO = PB02
|
||||
PIN_SPI_SCK = PB03
|
||||
PIN_SPI_SS = PB01
|
||||
|
||||
SS = PIN_SPI_SS
|
||||
MOSI = PIN_SPI_MOSI
|
||||
MISO = PIN_SPI_MISO
|
||||
SCK = PIN_SPI_SCK
|
||||
SS = PIN_SPI_SS
|
||||
SDO = PIN_SPI_SDO
|
||||
SDI = PIN_SPI_SDI
|
||||
SCK = PIN_SPI_SCK
|
||||
|
||||
// SPI1 RTL8720D_SPI
|
||||
PIN_SPI1_MISO = PC24
|
||||
PIN_SPI1_MOSI = PB24
|
||||
PIN_SPI1_SCK = PB25
|
||||
PIN_SPI1_SS = PC25
|
||||
PIN_SPI1_SDI = PC24
|
||||
PIN_SPI1_SDO = PB24
|
||||
PIN_SPI1_SCK = PB25
|
||||
PIN_SPI1_SS = PC25
|
||||
|
||||
SS1 = PIN_SPI1_SS
|
||||
MOSI1 = PIN_SPI1_MOSI
|
||||
MISO1 = PIN_SPI1_MISO
|
||||
SCK1 = PIN_SPI1_SCK
|
||||
SS1 = PIN_SPI1_SS
|
||||
SDO1 = PIN_SPI1_SDO
|
||||
SDI1 = PIN_SPI1_SDI
|
||||
SCK1 = PIN_SPI1_SCK
|
||||
|
||||
// SPI2 SD_SPI
|
||||
PIN_SPI2_MISO = PC18
|
||||
PIN_SPI2_MOSI = PC16
|
||||
PIN_SPI2_SCK = PC17
|
||||
PIN_SPI2_SS = PC19
|
||||
PIN_SPI2_SDI = PC18
|
||||
PIN_SPI2_SDO = PC16
|
||||
PIN_SPI2_SCK = PC17
|
||||
PIN_SPI2_SS = PC19
|
||||
|
||||
SS2 = PIN_SPI2_SS
|
||||
MOSI2 = PIN_SPI2_MOSI
|
||||
MISO2 = PIN_SPI2_MISO
|
||||
SCK2 = PIN_SPI2_SCK
|
||||
SS2 = PIN_SPI2_SS
|
||||
SDO2 = PIN_SPI2_SDO
|
||||
SDI2 = PIN_SPI2_SDI
|
||||
SCK2 = PIN_SPI2_SCK
|
||||
|
||||
// SPI3 LCD_SPI
|
||||
PIN_SPI3_MISO = PB18
|
||||
PIN_SPI3_MOSI = PB19
|
||||
PIN_SPI3_SCK = PB20
|
||||
PIN_SPI3_SS = PB21
|
||||
PIN_SPI3_SDI = PB18
|
||||
PIN_SPI3_SDO = PB19
|
||||
PIN_SPI3_SCK = PB20
|
||||
PIN_SPI3_SS = PB21
|
||||
|
||||
SS3 = PIN_SPI3_SS
|
||||
MOSI3 = PIN_SPI3_MOSI
|
||||
MISO3 = PIN_SPI3_MISO
|
||||
SCK3 = PIN_SPI3_SCK
|
||||
SS3 = PIN_SPI3_SS
|
||||
SDO3 = PIN_SPI3_SDO
|
||||
SDI3 = PIN_SPI3_SDI
|
||||
SCK3 = PIN_SPI3_SCK
|
||||
|
||||
// Needed for SD library
|
||||
SDCARD_MISO_PIN = PIN_SPI2_MISO
|
||||
SDCARD_MOSI_PIN = PIN_SPI2_MOSI
|
||||
SDCARD_SCK_PIN = PIN_SPI2_SCK
|
||||
SDCARD_SS_PIN = PIN_SPI2_SS
|
||||
SDCARD_DET_PIN = PD21
|
||||
SDCARD_SDI_PIN = PIN_SPI2_SDI
|
||||
SDCARD_SDO_PIN = PIN_SPI2_SDO
|
||||
SDCARD_SCK_PIN = PIN_SPI2_SCK
|
||||
SDCARD_SS_PIN = PIN_SPI2_SS
|
||||
SDCARD_DET_PIN = PD21
|
||||
|
||||
LCD_MISO_PIN = PIN_SPI3_MISO
|
||||
LCD_MOSI_PIN = PIN_SPI3_MOSI
|
||||
LCD_SDI_PIN = PIN_SPI3_SDI
|
||||
LCD_SDO_PIN = PIN_SPI3_SDO
|
||||
LCD_SCK_PIN = PIN_SPI3_SCK
|
||||
LCD_SS_PIN = PIN_SPI3_SS
|
||||
LCD_DC = PC06
|
||||
@@ -284,10 +281,10 @@ const (
|
||||
LCD_YD = PC13
|
||||
|
||||
// Needed for RTL8720D
|
||||
RTL8720D_MISO_PIN = PIN_SPI1_MISO
|
||||
RTL8720D_MOSI_PIN = PIN_SPI1_MOSI
|
||||
RTL8720D_SCK_PIN = PIN_SPI1_SCK
|
||||
RTL8720D_SS_PIN = PIN_SPI1_SS
|
||||
RTL8720D_SDI_PIN = PIN_SPI1_SDI
|
||||
RTL8720D_SDO_PIN = PIN_SPI1_SDO
|
||||
RTL8720D_SCK_PIN = PIN_SPI1_SCK
|
||||
RTL8720D_SS_PIN = PIN_SPI1_SS
|
||||
|
||||
//QSPI Pins
|
||||
PIN_QSPI_IO0 = PA08
|
||||
@@ -360,24 +357,24 @@ const (
|
||||
|
||||
// SPI pins
|
||||
const (
|
||||
SPI0_SCK_PIN = SCK // SCK: SERCOM5/PAD[1]
|
||||
SPI0_MOSI_PIN = MOSI // MOSI: SERCOM5/PAD[0]
|
||||
SPI0_MISO_PIN = MISO // MISO: SERCOM5/PAD[2]
|
||||
SPI0_SCK_PIN = SCK // SCK: SERCOM5/PAD[1]
|
||||
SPI0_SDO_PIN = SDO // SDO: SERCOM5/PAD[0]
|
||||
SPI0_SDI_PIN = SDI // SDI: SERCOM5/PAD[2]
|
||||
|
||||
// RTL8720D
|
||||
SPI1_SCK_PIN = SCK1 // SCK: SERCOM0/PAD[1]
|
||||
SPI1_MOSI_PIN = MOSI1 // MOSI: SERCOM0/PAD[0]
|
||||
SPI1_MISO_PIN = MISO1 // MISO: SERCOM0/PAD[2]
|
||||
SPI1_SCK_PIN = SCK1 // SCK: SERCOM0/PAD[1]
|
||||
SPI1_SDO_PIN = SDO1 // SDO: SERCOM0/PAD[0]
|
||||
SPI1_SDI_PIN = SDI1 // SDI: SERCOM0/PAD[2]
|
||||
|
||||
// SD
|
||||
SPI2_SCK_PIN = SCK2 // SCK: SERCOM6/PAD[1]
|
||||
SPI2_MOSI_PIN = MOSI2 // MOSI: SERCOM6/PAD[0]
|
||||
SPI2_MISO_PIN = MISO2 // MISO: SERCOM6/PAD[2]
|
||||
SPI2_SCK_PIN = SCK2 // SCK: SERCOM6/PAD[1]
|
||||
SPI2_SDO_PIN = SDO2 // SDO: SERCOM6/PAD[0]
|
||||
SPI2_SDI_PIN = SDI2 // SDI: SERCOM6/PAD[2]
|
||||
|
||||
// LCD
|
||||
SPI3_SCK_PIN = SCK3 // SCK: SERCOM7/PAD[1]
|
||||
SPI3_MOSI_PIN = MOSI3 // MOSI: SERCOM7/PAD[3]
|
||||
SPI3_MISO_PIN = MISO3 // MISO: SERCOM7/PAD[2]
|
||||
SPI3_SCK_PIN = SCK3 // SCK: SERCOM7/PAD[1]
|
||||
SPI3_SDO_PIN = SDO3 // SDO: SERCOM7/PAD[3]
|
||||
SPI3_SDI_PIN = SDI3 // SDI: SERCOM7/PAD[2]
|
||||
)
|
||||
|
||||
// USB CDC identifiers
|
||||
|
||||
@@ -4,14 +4,14 @@ package machine
|
||||
|
||||
// https://hackaday.io/project/144350-hacking-wearables-for-mental-health-and-more/details
|
||||
const (
|
||||
LED Pin = 4 // HR LED pin
|
||||
UART_TX_PIN Pin = NoPin
|
||||
UART_RX_PIN Pin = NoPin
|
||||
SCL_PIN Pin = NoPin
|
||||
SDA_PIN Pin = NoPin
|
||||
SPI0_SCK_PIN Pin = 18
|
||||
SPI0_MISO_PIN Pin = 19
|
||||
SPI0_MOSI_PIN Pin = 20
|
||||
LED Pin = 4 // HR LED pin
|
||||
UART_TX_PIN Pin = NoPin
|
||||
UART_RX_PIN Pin = NoPin
|
||||
SCL_PIN Pin = NoPin
|
||||
SDA_PIN Pin = NoPin
|
||||
SPI0_SCK_PIN Pin = 18
|
||||
SPI0_SDI_PIN Pin = 19
|
||||
SPI0_SDO_PIN Pin = 20
|
||||
)
|
||||
|
||||
// LCD pins.
|
||||
@@ -20,7 +20,7 @@ const (
|
||||
OLED_RES Pin = 14 // reset pin
|
||||
OLED_DC Pin = 13 // data/command
|
||||
OLED_SCK Pin = 12 // SPI clock
|
||||
OLED_MOSI Pin = 11 // SPI MOSI (master-out, slave-in)
|
||||
OLED_SDO Pin = 11 // SPI SDO (chip-out, peripheral-in)
|
||||
OLED_LED_POW Pin = 16
|
||||
OLED_IC_POW Pin = 17
|
||||
)
|
||||
|
||||
@@ -21,8 +21,8 @@ const (
|
||||
D6 = PB08 // can be used for PWM or UART1 TX
|
||||
D7 = PB09 // can be used for PWM or UART1 RX
|
||||
D8 = PA07 // can be used for PWM or SPI SCK
|
||||
D9 = PA05 // can be used for PWM or SPI MISO
|
||||
D10 = PA06 // can be used for PWM or SPI MOSI
|
||||
D9 = PA05 // can be used for PWM or SPI SDI
|
||||
D10 = PA06 // can be used for PWM or SPI SDO
|
||||
)
|
||||
|
||||
// Analog pins
|
||||
@@ -89,9 +89,9 @@ var (
|
||||
|
||||
// SPI pins
|
||||
const (
|
||||
SPI0_SCK_PIN = PA07 // SCK: SERCOM0/PAD[3]
|
||||
SPI0_MOSI_PIN = PA06 // MOSI: SERCOM0/PAD[2]
|
||||
SPI0_MISO_PIN = PA05 // MISO: SERCOM0/PAD[1]
|
||||
SPI0_SCK_PIN = PA07 // SCK: SERCOM0/PAD[3]
|
||||
SPI0_SDO_PIN = PA06 // SDO: SERCOM0/PAD[2]
|
||||
SPI0_SDI_PIN = PA05 // SDI: SERCOM0/PAD[1]
|
||||
)
|
||||
|
||||
// SPI on the Xiao
|
||||
|
||||
@@ -44,3 +44,9 @@ func (rb *RingBuffer) Get() (byte, bool) {
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// Clear resets the head and tail pointer to zero.
|
||||
func (rb *RingBuffer) Clear() {
|
||||
rb.head.Set(0)
|
||||
rb.tail.Set(0)
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// +build avr nrf sam stm32,!stm32f4disco fe310
|
||||
// +build avr nrf sam stm32,!stm32f4disco fe310 k210
|
||||
|
||||
package machine
|
||||
|
||||
|
||||
+12
-12
@@ -15,8 +15,8 @@ type I2SClockSource uint8
|
||||
type I2SDataFormat uint8
|
||||
|
||||
const (
|
||||
I2SModeMaster I2SMode = iota
|
||||
I2SModeSlave
|
||||
I2SModeSource I2SMode = iota
|
||||
I2SModeReceiver
|
||||
I2SModePDM
|
||||
)
|
||||
|
||||
@@ -41,14 +41,14 @@ const (
|
||||
|
||||
// All fields are optional and may not be required or used on a particular platform.
|
||||
type I2SConfig struct {
|
||||
SCK Pin
|
||||
WS Pin
|
||||
SD Pin
|
||||
Mode I2SMode
|
||||
Standard I2SStandard
|
||||
ClockSource I2SClockSource
|
||||
DataFormat I2SDataFormat
|
||||
AudioFrequency uint32
|
||||
MasterClockOutput bool
|
||||
Stereo bool
|
||||
SCK Pin
|
||||
WS Pin
|
||||
SD Pin
|
||||
Mode I2SMode
|
||||
Standard I2SStandard
|
||||
ClockSource I2SClockSource
|
||||
DataFormat I2SDataFormat
|
||||
AudioFrequency uint32
|
||||
MainClockOutput bool
|
||||
Stereo bool
|
||||
}
|
||||
|
||||
@@ -17,11 +17,11 @@ type PinConfig struct {
|
||||
// Pin is a single pin on a chip, which may be connected to other hardware
|
||||
// devices. It can either be used directly as GPIO pin or it can be used in
|
||||
// other peripherals like ADC, I2C, etc.
|
||||
type Pin int8
|
||||
type Pin uint8
|
||||
|
||||
// NoPin explicitly indicates "not a pin". Use this pin if you want to leave one
|
||||
// of the pins in a peripheral unconfigured (if supported by the hardware).
|
||||
const NoPin = Pin(-1)
|
||||
const NoPin = Pin(0xff)
|
||||
|
||||
// High sets this GPIO pin to high, assuming it has been configured as an output
|
||||
// pin. It is hardware dependent (and often undefined) what happens if you set a
|
||||
|
||||
@@ -27,7 +27,7 @@ func (i2c I2C) Configure(config I2CConfig) {
|
||||
|
||||
// twi bit rate formula from atmega128 manual pg. 204:
|
||||
// SCL Frequency = CPU Clock Frequency / (16 + (2 * TWBR))
|
||||
// NOTE: TWBR should be 10 or higher for master mode.
|
||||
// NOTE: TWBR should be 10 or higher for controller mode.
|
||||
// It is 72 for a 16mhz board with 100kHz TWI
|
||||
avr.TWBR.Set(uint8(((CPUFrequency() / config.Frequency) - 16) / 2))
|
||||
|
||||
|
||||
@@ -55,7 +55,8 @@ const (
|
||||
PD7 = portD + 7
|
||||
PE0 = portE + 0
|
||||
PE1 = portE + 1
|
||||
PE3 = portE + 2
|
||||
PE3 = portE + 3
|
||||
PE4 = portE + 4
|
||||
PE5 = portE + 5
|
||||
PE6 = portE + 6
|
||||
PF0 = portF + 0
|
||||
@@ -93,7 +94,7 @@ const (
|
||||
PL4 = portL + 4
|
||||
PL5 = portL + 5
|
||||
PL6 = portL + 6
|
||||
PL7 = portE + 7
|
||||
PL7 = portL + 7
|
||||
)
|
||||
|
||||
// getPortMask returns the PORTx register and mask for the pin.
|
||||
|
||||
@@ -240,7 +240,7 @@ func (p Pin) SetInterrupt(change PinChange, callback func(Pin)) error {
|
||||
addr = &sam.EIC.CONFIG1
|
||||
}
|
||||
pos := (extint % 8) * 4 // bit position in register
|
||||
addr.Set((addr.Get() &^ (0xf << pos)) | uint32(change)<<pos)
|
||||
addr.ReplaceBits(uint32(change), 0xf, pos)
|
||||
|
||||
// Enable external interrupt for this pin.
|
||||
sam.EIC.INTENSET.Set(1 << extint)
|
||||
@@ -648,7 +648,7 @@ func (i2c I2C) Configure(config I2CConfig) error {
|
||||
i2c.Bus.SYNCBUSY.HasBits(sam.SERCOM_I2CM_SYNCBUSY_SWRST) {
|
||||
}
|
||||
|
||||
// Set i2c master mode
|
||||
// Set i2c controller mode
|
||||
//SERCOM_I2CM_CTRLA_MODE( I2C_MASTER_OPERATION )
|
||||
i2c.Bus.CTRLA.Set(sam.SERCOM_I2CM_CTRLA_MODE_I2C_MASTER << sam.SERCOM_I2CM_CTRLA_MODE_Pos) // |
|
||||
|
||||
@@ -722,7 +722,7 @@ func (i2c I2C) Tx(addr uint16, w, r []byte) error {
|
||||
|
||||
// wait transmission complete
|
||||
for !i2c.Bus.INTFLAG.HasBits(sam.SERCOM_I2CM_INTFLAG_SB) {
|
||||
// If the slave NACKS the address, the MB bit will be set.
|
||||
// If the peripheral NACKS the address, the MB bit will be set.
|
||||
// In that case, send a stop condition and return error.
|
||||
if i2c.Bus.INTFLAG.HasBits(sam.SERCOM_I2CM_INTFLAG_MB) {
|
||||
i2c.Bus.CTRLB.SetBits(wireCmdStop << sam.SERCOM_I2CM_CTRLB_CMD_Pos) // Stop condition
|
||||
@@ -1074,8 +1074,8 @@ type SPI struct {
|
||||
type SPIConfig struct {
|
||||
Frequency uint32
|
||||
SCK Pin
|
||||
MOSI Pin
|
||||
MISO Pin
|
||||
SDO Pin
|
||||
SDI Pin
|
||||
LSBFirst bool
|
||||
Mode uint8
|
||||
}
|
||||
@@ -1083,10 +1083,10 @@ type SPIConfig struct {
|
||||
// Configure is intended to setup the SPI interface.
|
||||
func (spi SPI) Configure(config SPIConfig) error {
|
||||
// Use default pins if not set.
|
||||
if config.SCK == 0 && config.MOSI == 0 && config.MISO == 0 {
|
||||
if config.SCK == 0 && config.SDO == 0 && config.SDI == 0 {
|
||||
config.SCK = SPI0_SCK_PIN
|
||||
config.MOSI = SPI0_MOSI_PIN
|
||||
config.MISO = SPI0_MISO_PIN
|
||||
config.SDO = SPI0_SDO_PIN
|
||||
config.SDI = SPI0_SDI_PIN
|
||||
}
|
||||
|
||||
// set default frequency
|
||||
@@ -1094,27 +1094,27 @@ func (spi SPI) Configure(config SPIConfig) error {
|
||||
config.Frequency = 4000000
|
||||
}
|
||||
|
||||
// Determine the input pinout (for MISO).
|
||||
misoPinMode, misoPad, ok := findPinPadMapping(spi.SERCOM, config.MISO)
|
||||
// Determine the input pinout (for SDI).
|
||||
SDIPinMode, SDIPad, ok := findPinPadMapping(spi.SERCOM, config.SDI)
|
||||
if !ok {
|
||||
return ErrInvalidInputPin
|
||||
}
|
||||
dataInPinout := misoPad // mapped directly
|
||||
dataInPinout := SDIPad // mapped directly
|
||||
|
||||
// Determine the output pinout (for MOSI/SCK).
|
||||
// Determine the output pinout (for SDO/SCK).
|
||||
// See table 26-7 on page 494 of the datasheet.
|
||||
var dataOutPinout uint32
|
||||
sckPinMode, sckPad, ok := findPinPadMapping(spi.SERCOM, config.SCK)
|
||||
if !ok {
|
||||
return ErrInvalidOutputPin
|
||||
}
|
||||
mosiPinMode, mosiPad, ok := findPinPadMapping(spi.SERCOM, config.MOSI)
|
||||
SDOPinMode, SDOPad, ok := findPinPadMapping(spi.SERCOM, config.SDO)
|
||||
if !ok {
|
||||
return ErrInvalidOutputPin
|
||||
}
|
||||
switch sckPad {
|
||||
case 1:
|
||||
switch mosiPad {
|
||||
switch SDOPad {
|
||||
case 0:
|
||||
dataOutPinout = 0x0
|
||||
case 3:
|
||||
@@ -1123,7 +1123,7 @@ func (spi SPI) Configure(config SPIConfig) error {
|
||||
return ErrInvalidOutputPin
|
||||
}
|
||||
case 3:
|
||||
switch mosiPad {
|
||||
switch SDOPad {
|
||||
case 2:
|
||||
dataOutPinout = 0x1
|
||||
case 0:
|
||||
@@ -1142,8 +1142,8 @@ func (spi SPI) Configure(config SPIConfig) error {
|
||||
|
||||
// enable pins
|
||||
config.SCK.Configure(PinConfig{Mode: sckPinMode})
|
||||
config.MOSI.Configure(PinConfig{Mode: mosiPinMode})
|
||||
config.MISO.Configure(PinConfig{Mode: misoPinMode})
|
||||
config.SDO.Configure(PinConfig{Mode: SDOPinMode})
|
||||
config.SDI.Configure(PinConfig{Mode: SDIPinMode})
|
||||
|
||||
// reset SERCOM
|
||||
spi.Bus.CTRLA.SetBits(sam.SERCOM_SPI_CTRLA_SWRST)
|
||||
@@ -1157,7 +1157,7 @@ func (spi SPI) Configure(config SPIConfig) error {
|
||||
dataOrder = 1
|
||||
}
|
||||
|
||||
// Set SPI master
|
||||
// Set SPI mode to controller
|
||||
spi.Bus.CTRLA.Set((sam.SERCOM_SPI_CTRLA_MODE_SPI_MASTER << sam.SERCOM_SPI_CTRLA_MODE_Pos) |
|
||||
(dataOutPinout << sam.SERCOM_SPI_CTRLA_DOPO_Pos) |
|
||||
(dataInPinout << sam.SERCOM_SPI_CTRLA_DIPO_Pos) |
|
||||
@@ -2209,3 +2209,53 @@ func ResetProcessor() {
|
||||
|
||||
arm.SystemReset()
|
||||
}
|
||||
|
||||
// DAC on the SAMD21.
|
||||
type DAC struct {
|
||||
}
|
||||
|
||||
var (
|
||||
DAC0 = DAC{}
|
||||
)
|
||||
|
||||
// DACConfig placeholder for future expansion.
|
||||
type DACConfig struct {
|
||||
}
|
||||
|
||||
// Configure the DAC.
|
||||
// output pin must already be configured.
|
||||
func (dac DAC) Configure(config DACConfig) {
|
||||
// Turn on clock for DAC
|
||||
sam.PM.APBCMASK.SetBits(sam.PM_APBCMASK_DAC_)
|
||||
|
||||
// Use Generic Clock Generator 0 as source for DAC.
|
||||
sam.GCLK.CLKCTRL.Set((sam.GCLK_CLKCTRL_ID_DAC << sam.GCLK_CLKCTRL_ID_Pos) |
|
||||
(sam.GCLK_CLKCTRL_GEN_GCLK0 << sam.GCLK_CLKCTRL_GEN_Pos) |
|
||||
sam.GCLK_CLKCTRL_CLKEN)
|
||||
waitForSync()
|
||||
|
||||
// reset DAC
|
||||
sam.DAC.CTRLA.Set(sam.DAC_CTRLA_SWRST)
|
||||
syncDAC()
|
||||
|
||||
// wait for reset complete
|
||||
for sam.DAC.CTRLA.HasBits(sam.DAC_CTRLA_SWRST) {
|
||||
}
|
||||
|
||||
// enable
|
||||
sam.DAC.CTRLB.Set(sam.DAC_CTRLB_EOEN | sam.DAC_CTRLB_REFSEL_AVCC)
|
||||
sam.DAC.CTRLA.Set(sam.DAC_CTRLA_ENABLE)
|
||||
}
|
||||
|
||||
// Set writes a single 16-bit value to the DAC.
|
||||
// Since the ATSAMD21 only has a 10-bit DAC, the passed-in value will be scaled down.
|
||||
func (dac DAC) Set(value uint16) error {
|
||||
sam.DAC.DATA.Set(value >> 6)
|
||||
syncDAC()
|
||||
return nil
|
||||
}
|
||||
|
||||
func syncDAC() {
|
||||
for sam.DAC.STATUS.HasBits(sam.DAC_STATUS_SYNCBUSY) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -264,37 +264,37 @@ func (p Pin) setPMux(val uint8) {
|
||||
case 15:
|
||||
sam.PORT.PMUX0_15.Set(val)
|
||||
case 16:
|
||||
sam.PORT.PMUX1_0.Set(sam.PORT.PMUX1_0.Get()&^(0xff<<0) | (uint32(val) << 0))
|
||||
sam.PORT.PMUX1_0.ReplaceBits(uint32(val), 0xff, 0)
|
||||
case 17:
|
||||
sam.PORT.PMUX1_0.Set(sam.PORT.PMUX1_0.Get()&^(0xff<<8) | (uint32(val) << 8))
|
||||
sam.PORT.PMUX1_0.ReplaceBits(uint32(val), 0xff, 8)
|
||||
case 18:
|
||||
sam.PORT.PMUX1_0.Set(sam.PORT.PMUX1_0.Get()&^(0xff<<16) | (uint32(val) << 16))
|
||||
sam.PORT.PMUX1_0.ReplaceBits(uint32(val), 0xff, 16)
|
||||
case 19:
|
||||
sam.PORT.PMUX1_0.Set(sam.PORT.PMUX1_0.Get()&^(0xff<<24) | (uint32(val) << 24))
|
||||
sam.PORT.PMUX1_0.ReplaceBits(uint32(val), 0xff, 24)
|
||||
case 20:
|
||||
sam.PORT.PMUX1_4.Set(sam.PORT.PMUX1_4.Get()&^(0xff<<0) | (uint32(val) << 0))
|
||||
sam.PORT.PMUX1_4.ReplaceBits(uint32(val), 0xff, 0)
|
||||
case 21:
|
||||
sam.PORT.PMUX1_4.Set(sam.PORT.PMUX1_4.Get()&^(0xff<<8) | (uint32(val) << 8))
|
||||
sam.PORT.PMUX1_4.ReplaceBits(uint32(val), 0xff, 8)
|
||||
case 22:
|
||||
sam.PORT.PMUX1_4.Set(sam.PORT.PMUX1_4.Get()&^(0xff<<16) | (uint32(val) << 16))
|
||||
sam.PORT.PMUX1_4.ReplaceBits(uint32(val), 0xff, 16)
|
||||
case 23:
|
||||
sam.PORT.PMUX1_4.Set(sam.PORT.PMUX1_4.Get()&^(0xff<<24) | (uint32(val) << 24))
|
||||
sam.PORT.PMUX1_4.ReplaceBits(uint32(val), 0xff, 24)
|
||||
case 24:
|
||||
sam.PORT.PMUX1_8.Set(sam.PORT.PMUX1_8.Get()&^(0xff<<0) | (uint32(val) << 0))
|
||||
sam.PORT.PMUX1_8.ReplaceBits(uint32(val), 0xff, 0)
|
||||
case 25:
|
||||
sam.PORT.PMUX1_8.Set(sam.PORT.PMUX1_8.Get()&^(0xff<<8) | (uint32(val) << 8))
|
||||
sam.PORT.PMUX1_8.ReplaceBits(uint32(val), 0xff, 8)
|
||||
case 26:
|
||||
sam.PORT.PMUX1_8.Set(sam.PORT.PMUX1_8.Get()&^(0xff<<16) | (uint32(val) << 16))
|
||||
sam.PORT.PMUX1_8.ReplaceBits(uint32(val), 0xff, 16)
|
||||
case 27:
|
||||
sam.PORT.PMUX1_8.Set(sam.PORT.PMUX1_8.Get()&^(0xff<<24) | (uint32(val) << 24))
|
||||
sam.PORT.PMUX1_8.ReplaceBits(uint32(val), 0xff, 24)
|
||||
case 28:
|
||||
sam.PORT.PMUX1_12.Set(sam.PORT.PMUX1_12.Get()&^(0xff<<0) | (uint32(val) << 0))
|
||||
sam.PORT.PMUX1_12.ReplaceBits(uint32(val), 0xff, 0)
|
||||
case 29:
|
||||
sam.PORT.PMUX1_12.Set(sam.PORT.PMUX1_12.Get()&^(0xff<<8) | (uint32(val) << 8))
|
||||
sam.PORT.PMUX1_12.ReplaceBits(uint32(val), 0xff, 8)
|
||||
case 30:
|
||||
sam.PORT.PMUX1_12.Set(sam.PORT.PMUX1_12.Get()&^(0xff<<16) | (uint32(val) << 16))
|
||||
sam.PORT.PMUX1_12.ReplaceBits(uint32(val), 0xff, 16)
|
||||
case 31:
|
||||
sam.PORT.PMUX1_12.Set(sam.PORT.PMUX1_12.Get()&^(0xff<<24) | (uint32(val) << 24))
|
||||
sam.PORT.PMUX1_12.ReplaceBits(uint32(val), 0xff, 24)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -502,68 +502,68 @@ func (p Pin) setPinCfg(val uint8) {
|
||||
case 31:
|
||||
sam.PORT.PINCFG0_31.Set(val)
|
||||
case 32: // PB00
|
||||
sam.PORT.PINCFG1_0.Set(sam.PORT.PINCFG1_0.Get()&^(0xff<<0) | (uint32(val) << 0))
|
||||
sam.PORT.PINCFG1_0.ReplaceBits(uint32(val), 0xff, 0)
|
||||
case 33: // PB01
|
||||
sam.PORT.PINCFG1_0.Set(sam.PORT.PINCFG1_0.Get()&^(0xff<<8) | (uint32(val) << 8))
|
||||
sam.PORT.PINCFG1_0.ReplaceBits(uint32(val), 0xff, 8)
|
||||
case 34: // PB02
|
||||
sam.PORT.PINCFG1_0.Set(sam.PORT.PINCFG1_0.Get()&^(0xff<<16) | (uint32(val) << 16))
|
||||
sam.PORT.PINCFG1_0.ReplaceBits(uint32(val), 0xff, 16)
|
||||
case 35: // PB03
|
||||
sam.PORT.PINCFG1_0.Set(sam.PORT.PINCFG1_0.Get()&^(0xff<<24) | (uint32(val) << 24))
|
||||
sam.PORT.PINCFG1_0.ReplaceBits(uint32(val), 0xff, 24)
|
||||
case 36: // PB04
|
||||
sam.PORT.PINCFG1_4.Set(sam.PORT.PINCFG1_4.Get()&^(0xff<<0) | (uint32(val) << 0))
|
||||
sam.PORT.PINCFG1_4.ReplaceBits(uint32(val), 0xff, 0)
|
||||
case 37: // PB05
|
||||
sam.PORT.PINCFG1_4.Set(sam.PORT.PINCFG1_4.Get()&^(0xff<<8) | (uint32(val) << 8))
|
||||
sam.PORT.PINCFG1_4.ReplaceBits(uint32(val), 0xff, 8)
|
||||
case 38: // PB06
|
||||
sam.PORT.PINCFG1_4.Set(sam.PORT.PINCFG1_4.Get()&^(0xff<<16) | (uint32(val) << 16))
|
||||
sam.PORT.PINCFG1_4.ReplaceBits(uint32(val), 0xff, 16)
|
||||
case 39: // PB07
|
||||
sam.PORT.PINCFG1_4.Set(sam.PORT.PINCFG1_4.Get()&^(0xff<<24) | (uint32(val) << 24))
|
||||
sam.PORT.PINCFG1_4.ReplaceBits(uint32(val), 0xff, 24)
|
||||
case 40: // PB08
|
||||
sam.PORT.PINCFG1_8.Set(sam.PORT.PINCFG1_8.Get()&^(0xff<<0) | (uint32(val) << 0))
|
||||
sam.PORT.PINCFG1_8.ReplaceBits(uint32(val), 0xff, 0)
|
||||
case 41: // PB09
|
||||
sam.PORT.PINCFG1_8.Set(sam.PORT.PINCFG1_8.Get()&^(0xff<<8) | (uint32(val) << 8))
|
||||
sam.PORT.PINCFG1_8.ReplaceBits(uint32(val), 0xff, 8)
|
||||
case 42: // PB10
|
||||
sam.PORT.PINCFG1_8.Set(sam.PORT.PINCFG1_8.Get()&^(0xff<<16) | (uint32(val) << 16))
|
||||
sam.PORT.PINCFG1_8.ReplaceBits(uint32(val), 0xff, 16)
|
||||
case 43: // PB11
|
||||
sam.PORT.PINCFG1_8.Set(sam.PORT.PINCFG1_8.Get()&^(0xff<<24) | (uint32(val) << 24))
|
||||
sam.PORT.PINCFG1_8.ReplaceBits(uint32(val), 0xff, 24)
|
||||
case 44: // PB12
|
||||
sam.PORT.PINCFG1_12.Set(sam.PORT.PINCFG1_12.Get()&^(0xff<<0) | (uint32(val) << 0))
|
||||
sam.PORT.PINCFG1_12.ReplaceBits(uint32(val), 0xff, 0)
|
||||
case 45: // PB13
|
||||
sam.PORT.PINCFG1_12.Set(sam.PORT.PINCFG1_12.Get()&^(0xff<<8) | (uint32(val) << 8))
|
||||
sam.PORT.PINCFG1_12.ReplaceBits(uint32(val), 0xff, 8)
|
||||
case 46: // PB14
|
||||
sam.PORT.PINCFG1_12.Set(sam.PORT.PINCFG1_12.Get()&^(0xff<<16) | (uint32(val) << 16))
|
||||
sam.PORT.PINCFG1_12.ReplaceBits(uint32(val), 0xff, 16)
|
||||
case 47: // PB15
|
||||
sam.PORT.PINCFG1_12.Set(sam.PORT.PINCFG1_12.Get()&^(0xff<<24) | (uint32(val) << 24))
|
||||
sam.PORT.PINCFG1_12.ReplaceBits(uint32(val), 0xff, 24)
|
||||
case 48: // PB16
|
||||
sam.PORT.PINCFG1_16.Set(sam.PORT.PINCFG1_16.Get()&^(0xff<<0) | (uint32(val) << 0))
|
||||
sam.PORT.PINCFG1_16.ReplaceBits(uint32(val), 0xff, 0)
|
||||
case 49: // PB17
|
||||
sam.PORT.PINCFG1_16.Set(sam.PORT.PINCFG1_16.Get()&^(0xff<<8) | (uint32(val) << 8))
|
||||
sam.PORT.PINCFG1_16.ReplaceBits(uint32(val), 0xff, 8)
|
||||
case 50: // PB18
|
||||
sam.PORT.PINCFG1_16.Set(sam.PORT.PINCFG1_16.Get()&^(0xff<<16) | (uint32(val) << 16))
|
||||
sam.PORT.PINCFG1_16.ReplaceBits(uint32(val), 0xff, 16)
|
||||
case 51: // PB19
|
||||
sam.PORT.PINCFG1_16.Set(sam.PORT.PINCFG1_16.Get()&^(0xff<<24) | (uint32(val) << 24))
|
||||
sam.PORT.PINCFG1_16.ReplaceBits(uint32(val), 0xff, 24)
|
||||
case 52: // PB20
|
||||
sam.PORT.PINCFG1_20.Set(sam.PORT.PINCFG1_20.Get()&^(0xff<<0) | (uint32(val) << 0))
|
||||
sam.PORT.PINCFG1_20.ReplaceBits(uint32(val), 0xff, 0)
|
||||
case 53: // PB21
|
||||
sam.PORT.PINCFG1_20.Set(sam.PORT.PINCFG1_20.Get()&^(0xff<<8) | (uint32(val) << 8))
|
||||
sam.PORT.PINCFG1_20.ReplaceBits(uint32(val), 0xff, 8)
|
||||
case 54: // PB22
|
||||
sam.PORT.PINCFG1_20.Set(sam.PORT.PINCFG1_20.Get()&^(0xff<<16) | (uint32(val) << 16))
|
||||
sam.PORT.PINCFG1_20.ReplaceBits(uint32(val), 0xff, 16)
|
||||
case 55: // PB23
|
||||
sam.PORT.PINCFG1_20.Set(sam.PORT.PINCFG1_20.Get()&^(0xff<<24) | (uint32(val) << 24))
|
||||
sam.PORT.PINCFG1_20.ReplaceBits(uint32(val), 0xff, 24)
|
||||
case 56: // PB24
|
||||
sam.PORT.PINCFG1_24.Set(sam.PORT.PINCFG1_24.Get()&^(0xff<<0) | (uint32(val) << 0))
|
||||
sam.PORT.PINCFG1_24.ReplaceBits(uint32(val), 0xff, 0)
|
||||
case 57: // PB25
|
||||
sam.PORT.PINCFG1_24.Set(sam.PORT.PINCFG1_24.Get()&^(0xff<<8) | (uint32(val) << 8))
|
||||
sam.PORT.PINCFG1_24.ReplaceBits(uint32(val), 0xff, 8)
|
||||
case 58: // PB26
|
||||
sam.PORT.PINCFG1_24.Set(sam.PORT.PINCFG1_24.Get()&^(0xff<<16) | (uint32(val) << 16))
|
||||
sam.PORT.PINCFG1_24.ReplaceBits(uint32(val), 0xff, 16)
|
||||
case 59: // PB27
|
||||
sam.PORT.PINCFG1_24.Set(sam.PORT.PINCFG1_24.Get()&^(0xff<<24) | (uint32(val) << 24))
|
||||
sam.PORT.PINCFG1_24.ReplaceBits(uint32(val), 0xff, 24)
|
||||
case 60: // PB28
|
||||
sam.PORT.PINCFG1_28.Set(sam.PORT.PINCFG1_28.Get()&^(0xff<<0) | (uint32(val) << 0))
|
||||
sam.PORT.PINCFG1_28.ReplaceBits(uint32(val), 0xff, 0)
|
||||
case 61: // PB29
|
||||
sam.PORT.PINCFG1_28.Set(sam.PORT.PINCFG1_28.Get()&^(0xff<<8) | (uint32(val) << 8))
|
||||
sam.PORT.PINCFG1_28.ReplaceBits(uint32(val), 0xff, 8)
|
||||
case 62: // PB30
|
||||
sam.PORT.PINCFG1_28.Set(sam.PORT.PINCFG1_28.Get()&^(0xff<<16) | (uint32(val) << 16))
|
||||
sam.PORT.PINCFG1_28.ReplaceBits(uint32(val), 0xff, 16)
|
||||
case 63: // PB31
|
||||
sam.PORT.PINCFG1_28.Set(sam.PORT.PINCFG1_28.Get()&^(0xff<<24) | (uint32(val) << 24))
|
||||
sam.PORT.PINCFG1_28.ReplaceBits(uint32(val), 0xff, 24)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -438,7 +438,7 @@ func (p Pin) SetInterrupt(change PinChange, callback func(Pin)) error {
|
||||
addr = &sam.EIC.CONFIG[1]
|
||||
}
|
||||
pos := (extint % 8) * 4 // bit position in register
|
||||
addr.Set((addr.Get() &^ (0xf << pos)) | uint32(change)<<pos)
|
||||
addr.ReplaceBits(uint32(change), 0xf, pos)
|
||||
|
||||
// Enable external interrupt for this pin.
|
||||
sam.EIC.INTENSET.Set(1 << extint)
|
||||
@@ -1111,7 +1111,7 @@ func (i2c I2C) Configure(config I2CConfig) error {
|
||||
i2c.Bus.SYNCBUSY.HasBits(sam.SERCOM_I2CM_SYNCBUSY_SWRST) {
|
||||
}
|
||||
|
||||
// Set i2c master mode
|
||||
// Set i2c controller mode
|
||||
//SERCOM_I2CM_CTRLA_MODE( I2C_MASTER_OPERATION )
|
||||
// sam.SERCOM_I2CM_CTRLA_MODE_I2C_MASTER = 5?
|
||||
i2c.Bus.CTRLA.Set(5 << sam.SERCOM_I2CM_CTRLA_MODE_Pos) // |
|
||||
@@ -1186,7 +1186,7 @@ func (i2c I2C) Tx(addr uint16, w, r []byte) error {
|
||||
|
||||
// wait transmission complete
|
||||
for !i2c.Bus.INTFLAG.HasBits(sam.SERCOM_I2CM_INTFLAG_SB) {
|
||||
// If the slave NACKS the address, the MB bit will be set.
|
||||
// If the peripheral NACKS the address, the MB bit will be set.
|
||||
// In that case, send a stop condition and return error.
|
||||
if i2c.Bus.INTFLAG.HasBits(sam.SERCOM_I2CM_INTFLAG_MB) {
|
||||
i2c.Bus.CTRLB.SetBits(wireCmdStop << sam.SERCOM_I2CM_CTRLB_CMD_Pos) // Stop condition
|
||||
@@ -1309,8 +1309,8 @@ type SPI struct {
|
||||
type SPIConfig struct {
|
||||
Frequency uint32
|
||||
SCK Pin
|
||||
MOSI Pin
|
||||
MISO Pin
|
||||
SDO Pin
|
||||
SDI Pin
|
||||
LSBFirst bool
|
||||
Mode uint8
|
||||
}
|
||||
@@ -1318,10 +1318,10 @@ type SPIConfig struct {
|
||||
// Configure is intended to setup the SPI interface.
|
||||
func (spi SPI) Configure(config SPIConfig) error {
|
||||
// Use default pins if not set.
|
||||
if config.SCK == 0 && config.MOSI == 0 && config.MISO == 0 {
|
||||
if config.SCK == 0 && config.SDO == 0 && config.SDI == 0 {
|
||||
config.SCK = SPI0_SCK_PIN
|
||||
config.MOSI = SPI0_MOSI_PIN
|
||||
config.MISO = SPI0_MISO_PIN
|
||||
config.SDO = SPI0_SDO_PIN
|
||||
config.SDI = SPI0_SDI_PIN
|
||||
}
|
||||
|
||||
// set default frequency
|
||||
@@ -1329,17 +1329,17 @@ func (spi SPI) Configure(config SPIConfig) error {
|
||||
config.Frequency = 4000000
|
||||
}
|
||||
|
||||
// Determine the input pinout (for MISO).
|
||||
// Determine the input pinout (for SDI).
|
||||
var dataInPinout uint32
|
||||
misoPinMode, misoPad, ok := findPinPadMapping(spi.SERCOM, config.MISO)
|
||||
if config.MISO != NoPin {
|
||||
SDIPinMode, SDIPad, ok := findPinPadMapping(spi.SERCOM, config.SDI)
|
||||
if config.SDI != NoPin {
|
||||
if !ok {
|
||||
return ErrInvalidInputPin
|
||||
}
|
||||
dataInPinout = misoPad // mapped directly
|
||||
dataInPinout = SDIPad // mapped directly
|
||||
}
|
||||
|
||||
// Determine the output pinout (for MOSI/SCK).
|
||||
// Determine the output pinout (for SDO/SCK).
|
||||
// See DOPO field in the CTRLA register on page 986 of the datasheet.
|
||||
var dataOutPinout uint32
|
||||
sckPinMode, sckPad, ok := findPinPadMapping(spi.SERCOM, config.SCK)
|
||||
@@ -1347,11 +1347,11 @@ func (spi SPI) Configure(config SPIConfig) error {
|
||||
// SCK pad must always be 1
|
||||
return ErrInvalidOutputPin
|
||||
}
|
||||
mosiPinMode, mosiPad, ok := findPinPadMapping(spi.SERCOM, config.MOSI)
|
||||
SDOPinMode, SDOPad, ok := findPinPadMapping(spi.SERCOM, config.SDO)
|
||||
if !ok {
|
||||
return ErrInvalidOutputPin
|
||||
}
|
||||
switch mosiPad {
|
||||
switch SDOPad {
|
||||
case 0:
|
||||
dataOutPinout = 0x0
|
||||
case 3:
|
||||
@@ -1367,9 +1367,9 @@ func (spi SPI) Configure(config SPIConfig) error {
|
||||
|
||||
// enable pins
|
||||
config.SCK.Configure(PinConfig{Mode: sckPinMode})
|
||||
config.MOSI.Configure(PinConfig{Mode: mosiPinMode})
|
||||
if config.MISO != NoPin {
|
||||
config.MISO.Configure(PinConfig{Mode: misoPinMode})
|
||||
config.SDO.Configure(PinConfig{Mode: SDOPinMode})
|
||||
if config.SDI != NoPin {
|
||||
config.SDI.Configure(PinConfig{Mode: SDIPinMode})
|
||||
}
|
||||
|
||||
// reset SERCOM
|
||||
@@ -1384,7 +1384,7 @@ func (spi SPI) Configure(config SPIConfig) error {
|
||||
dataOrder = 1
|
||||
}
|
||||
|
||||
// Set SPI master
|
||||
// Set SPI controller
|
||||
// SERCOM_SPIM_CTRLA_MODE_SPI_MASTER = 3
|
||||
spi.Bus.CTRLA.Set((3 << sam.SERCOM_SPIM_CTRLA_MODE_Pos) |
|
||||
(dataOutPinout << sam.SERCOM_SPIM_CTRLA_DOPO_Pos) |
|
||||
@@ -2297,3 +2297,61 @@ func ResetProcessor() {
|
||||
|
||||
arm.SystemReset()
|
||||
}
|
||||
|
||||
// DAC on the SAMD51.
|
||||
type DAC struct {
|
||||
}
|
||||
|
||||
var (
|
||||
DAC0 = DAC{}
|
||||
)
|
||||
|
||||
// DACConfig placeholder for future expansion.
|
||||
type DACConfig struct {
|
||||
}
|
||||
|
||||
// Configure the DAC.
|
||||
// output pin must already be configured.
|
||||
func (dac DAC) Configure(config DACConfig) {
|
||||
// Turn on clock for DAC
|
||||
sam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_DAC_)
|
||||
|
||||
// Use Generic Clock Generator 4 as source for DAC.
|
||||
sam.GCLK.PCHCTRL[42].Set((sam.GCLK_PCHCTRL_GEN_GCLK4 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)
|
||||
for sam.GCLK.SYNCBUSY.HasBits(sam.GCLK_SYNCBUSY_GENCTRL_GCLK4 << sam.GCLK_SYNCBUSY_GENCTRL_Pos) {
|
||||
}
|
||||
|
||||
// reset DAC
|
||||
sam.DAC.CTRLA.Set(sam.DAC_CTRLA_SWRST)
|
||||
|
||||
// wait for reset complete
|
||||
for sam.DAC.CTRLA.HasBits(sam.DAC_CTRLA_SWRST) {
|
||||
}
|
||||
for sam.DAC.SYNCBUSY.HasBits(sam.DAC_SYNCBUSY_SWRST) {
|
||||
}
|
||||
|
||||
// enable
|
||||
sam.DAC.CTRLB.Set(sam.DAC_CTRLB_REFSEL_VREFPU << sam.DAC_CTRLB_REFSEL_Pos)
|
||||
sam.DAC.DACCTRL[0].SetBits((sam.DAC_DACCTRL_CCTRL_CC12M << sam.DAC_DACCTRL_CCTRL_Pos) | sam.DAC_DACCTRL_ENABLE)
|
||||
sam.DAC.CTRLA.Set(sam.DAC_CTRLA_ENABLE)
|
||||
|
||||
for sam.DAC.SYNCBUSY.HasBits(sam.DAC_SYNCBUSY_ENABLE) {
|
||||
}
|
||||
for !sam.DAC.STATUS.HasBits(sam.DAC_STATUS_READY0) {
|
||||
}
|
||||
}
|
||||
|
||||
// Set writes a single 16-bit value to the DAC.
|
||||
// Since the ATSAMD51 only has a 12-bit DAC, the passed-in value will be scaled down.
|
||||
func (dac DAC) Set(value uint16) error {
|
||||
sam.DAC.DATA[0].Set(value >> 4)
|
||||
syncDAC()
|
||||
return nil
|
||||
}
|
||||
|
||||
func syncDAC() {
|
||||
for !sam.DAC.STATUS.HasBits(sam.DAC_STATUS_EOC0) {
|
||||
}
|
||||
for sam.DAC.SYNCBUSY.HasBits(sam.DAC_SYNCBUSY_DATA0) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,8 +101,8 @@ type SPI struct {
|
||||
type SPIConfig struct {
|
||||
Frequency uint32
|
||||
SCK Pin
|
||||
MOSI Pin
|
||||
MISO Pin
|
||||
SDO Pin
|
||||
SDI Pin
|
||||
LSBFirst bool
|
||||
Mode uint8
|
||||
}
|
||||
@@ -110,16 +110,16 @@ type SPIConfig struct {
|
||||
// Configure is intended to setup the SPI interface.
|
||||
func (spi SPI) Configure(config SPIConfig) error {
|
||||
// Use default pins if not set.
|
||||
if config.SCK == 0 && config.MOSI == 0 && config.MISO == 0 {
|
||||
if config.SCK == 0 && config.SDO == 0 && config.SDI == 0 {
|
||||
config.SCK = SPI0_SCK_PIN
|
||||
config.MOSI = SPI0_MOSI_PIN
|
||||
config.MISO = SPI0_MISO_PIN
|
||||
config.SDO = SPI0_SDO_PIN
|
||||
config.SDI = SPI0_SDI_PIN
|
||||
}
|
||||
|
||||
// enable pins for SPI
|
||||
config.SCK.Configure(PinConfig{Mode: PinSPI})
|
||||
config.MOSI.Configure(PinConfig{Mode: PinSPI})
|
||||
config.MISO.Configure(PinConfig{Mode: PinSPI})
|
||||
config.SDO.Configure(PinConfig{Mode: PinSPI})
|
||||
config.SDI.Configure(PinConfig{Mode: PinSPI})
|
||||
|
||||
// set default frequency
|
||||
if config.Frequency == 0 {
|
||||
|
||||
@@ -47,13 +47,13 @@ type SPI struct {
|
||||
type SPIConfig struct {
|
||||
Frequency uint32
|
||||
SCK Pin
|
||||
MOSI Pin
|
||||
MISO Pin
|
||||
SDO Pin
|
||||
SDI Pin
|
||||
Mode uint8
|
||||
}
|
||||
|
||||
func (spi SPI) Configure(config SPIConfig) {
|
||||
spiConfigure(spi.Bus, config.SCK, config.MOSI, config.MISO)
|
||||
spiConfigure(spi.Bus, config.SCK, config.SDO, config.SDI)
|
||||
}
|
||||
|
||||
// Transfer writes/reads a single byte using the SPI interface.
|
||||
@@ -62,7 +62,7 @@ func (spi SPI) Transfer(w byte) (byte, error) {
|
||||
}
|
||||
|
||||
//export __tinygo_spi_configure
|
||||
func spiConfigure(bus uint8, sck Pin, mosi Pin, miso Pin)
|
||||
func spiConfigure(bus uint8, sck Pin, SDO Pin, SDI Pin)
|
||||
|
||||
//export __tinygo_spi_transfer
|
||||
func spiTransfer(bus uint8, w uint8) uint8
|
||||
|
||||
@@ -0,0 +1,635 @@
|
||||
// +build k210
|
||||
|
||||
package machine
|
||||
|
||||
import (
|
||||
"device/kendryte"
|
||||
"device/riscv"
|
||||
"errors"
|
||||
"runtime/interrupt"
|
||||
)
|
||||
|
||||
func CPUFrequency() uint32 {
|
||||
return 390000000
|
||||
}
|
||||
|
||||
type PinMode uint8
|
||||
type fpioaPullMode uint8
|
||||
type PinChange uint8
|
||||
|
||||
// Pin modes.
|
||||
const (
|
||||
PinInput PinMode = iota
|
||||
PinInputPullUp
|
||||
PinInputPullDown
|
||||
PinOutput
|
||||
)
|
||||
|
||||
// FPIOA internal pull resistors.
|
||||
const (
|
||||
fpioaPullNone fpioaPullMode = iota
|
||||
fpioaPullDown
|
||||
fpioaPullUp
|
||||
)
|
||||
|
||||
// GPIOHS pin interrupt events.
|
||||
const (
|
||||
PinRising PinChange = 1 << iota
|
||||
PinFalling
|
||||
PinToggle = PinRising | PinFalling
|
||||
)
|
||||
|
||||
var (
|
||||
errUnsupportedSPIController = errors.New("SPI controller not supported. Use SPI0 or SPI1.")
|
||||
errI2CTxAbort = errors.New("I2C transmition has been aborted.")
|
||||
)
|
||||
|
||||
func (p Pin) setFPIOAIOPull(pull fpioaPullMode) {
|
||||
switch pull {
|
||||
case fpioaPullNone:
|
||||
kendryte.FPIOA.IO[uint8(p)].ClearBits(kendryte.FPIOA_IO_PU & kendryte.FPIOA_IO_PD)
|
||||
case fpioaPullUp:
|
||||
kendryte.FPIOA.IO[uint8(p)].SetBits(kendryte.FPIOA_IO_PU)
|
||||
kendryte.FPIOA.IO[uint8(p)].ClearBits(kendryte.FPIOA_IO_PD)
|
||||
case fpioaPullDown:
|
||||
kendryte.FPIOA.IO[uint8(p)].ClearBits(kendryte.FPIOA_IO_PU)
|
||||
kendryte.FPIOA.IO[uint8(p)].SetBits(kendryte.FPIOA_IO_PD)
|
||||
}
|
||||
}
|
||||
|
||||
// SetFPIOAFunction is used to configure the pin for one of the FPIOA functions.
|
||||
// Each pin on the Kendryte K210 can be configured with any of the available FPIOA functions.
|
||||
func (p Pin) SetFPIOAFunction(f FPIOAFunction) {
|
||||
kendryte.FPIOA.IO[uint8(p)].Set(fpioaFuncDefaults[uint8(f)])
|
||||
}
|
||||
|
||||
// FPIOAFunction returns the current FPIOA function of the pin.
|
||||
func (p Pin) FPIOAFunction() FPIOAFunction {
|
||||
return FPIOAFunction((kendryte.FPIOA.IO[uint8(p)].Get() & kendryte.FPIOA_IO_CH_SEL_Msk))
|
||||
}
|
||||
|
||||
// Configure this pin with the given configuration.
|
||||
// The pin must already be set as GPIO or GPIOHS pin.
|
||||
func (p Pin) Configure(config PinConfig) {
|
||||
var input bool
|
||||
|
||||
// Check if the current pin's FPIOA function is either GPIO or GPIOHS.
|
||||
f := p.FPIOAFunction()
|
||||
if f < FUNC_GPIOHS0 || f > FUNC_GPIO7 {
|
||||
return // The pin is not configured as GPIO or GPIOHS.
|
||||
}
|
||||
|
||||
// Configure pin.
|
||||
kendryte.FPIOA.IO[uint8(p)].SetBits(kendryte.FPIOA_IO_OE_EN | kendryte.FPIOA_IO_IE_EN | kendryte.FPIOA_IO_ST | kendryte.FPIOA_IO_DS_Msk)
|
||||
|
||||
switch config.Mode {
|
||||
case PinInput:
|
||||
p.setFPIOAIOPull(fpioaPullNone)
|
||||
input = true
|
||||
case PinInputPullUp:
|
||||
p.setFPIOAIOPull(fpioaPullUp)
|
||||
input = true
|
||||
case PinInputPullDown:
|
||||
p.setFPIOAIOPull(fpioaPullDown)
|
||||
input = true
|
||||
case PinOutput:
|
||||
p.setFPIOAIOPull(fpioaPullNone)
|
||||
input = false
|
||||
}
|
||||
|
||||
if f >= FUNC_GPIO0 && f <= FUNC_GPIO7 {
|
||||
// Converts the IO pin number in the effective GPIO number (based on the FPIOA function).
|
||||
gpioPin := uint8(f - FUNC_GPIO0)
|
||||
|
||||
if input {
|
||||
kendryte.GPIO.DIRECTION.ClearBits(1 << gpioPin)
|
||||
} else {
|
||||
kendryte.GPIO.DIRECTION.SetBits(1 << gpioPin)
|
||||
}
|
||||
} else if f >= FUNC_GPIOHS0 && f <= FUNC_GPIOHS31 {
|
||||
// Converts the IO pin number in the effective GPIOHS number (based on the FPIOA function).
|
||||
gpioPin := uint8(f - FUNC_GPIOHS0)
|
||||
|
||||
if input {
|
||||
kendryte.GPIOHS.INPUT_EN.SetBits(1 << gpioPin)
|
||||
kendryte.GPIOHS.OUTPUT_EN.ClearBits(1 << gpioPin)
|
||||
} else {
|
||||
kendryte.GPIOHS.OUTPUT_EN.SetBits(1 << gpioPin)
|
||||
kendryte.GPIOHS.INPUT_EN.ClearBits(1 << gpioPin)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set the pin to high or low.
|
||||
func (p Pin) Set(high bool) {
|
||||
|
||||
// Check if the current pin's FPIOA function is either GPIO or GPIOHS.
|
||||
f := p.FPIOAFunction()
|
||||
if f < FUNC_GPIOHS0 || f > FUNC_GPIO7 {
|
||||
return // The pin is not configured as GPIO or GPIOHS.
|
||||
}
|
||||
|
||||
if f >= FUNC_GPIO0 && f <= FUNC_GPIO7 {
|
||||
gpioPin := uint8(f - FUNC_GPIO0)
|
||||
|
||||
if high {
|
||||
kendryte.GPIO.DATA_OUTPUT.SetBits(1 << gpioPin)
|
||||
} else {
|
||||
kendryte.GPIO.DATA_OUTPUT.ClearBits(1 << gpioPin)
|
||||
}
|
||||
} else if f >= FUNC_GPIOHS0 && f <= FUNC_GPIOHS31 {
|
||||
gpioPin := uint8(f - FUNC_GPIOHS0)
|
||||
|
||||
if high {
|
||||
kendryte.GPIOHS.OUTPUT_VAL.SetBits(1 << gpioPin)
|
||||
} else {
|
||||
kendryte.GPIOHS.OUTPUT_VAL.ClearBits(1 << gpioPin)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get returns the current value of a GPIO pin.
|
||||
func (p Pin) Get() bool {
|
||||
|
||||
// Check if the current pin's FPIOA function is either GPIO or GPIOHS.
|
||||
f := p.FPIOAFunction()
|
||||
if f < FUNC_GPIOHS0 || f > FUNC_GPIO7 {
|
||||
return false // The pin is not configured as GPIO or GPIOHS.
|
||||
}
|
||||
|
||||
var val uint32
|
||||
if f >= FUNC_GPIO0 && f <= FUNC_GPIO7 {
|
||||
gpioPin := uint8(f - FUNC_GPIO0)
|
||||
val = kendryte.GPIO.DATA_INPUT.Get() & (1 << gpioPin)
|
||||
} else if f >= FUNC_GPIOHS0 && f <= FUNC_GPIOHS31 {
|
||||
gpioPin := uint8(f - FUNC_GPIOHS0)
|
||||
val = kendryte.GPIOHS.INPUT_VAL.Get() & (1 << gpioPin)
|
||||
}
|
||||
return (val > 0)
|
||||
}
|
||||
|
||||
// Callbacks to be called for GPIOHS pins configured with SetInterrupt.
|
||||
var pinCallbacks [32]func(Pin)
|
||||
|
||||
// SetInterrupt sets an interrupt to be executed when a particular pin changes
|
||||
// state.
|
||||
//
|
||||
// You can pass a nil func to unset the pin change interrupt. If you do so,
|
||||
// the change parameter is ignored and can be set to any value (such as 0).
|
||||
// If the pin is already configured with a callback, you must first unset
|
||||
// this pins interrupt before you can set a new callback.
|
||||
func (p Pin) SetInterrupt(change PinChange, callback func(Pin)) error {
|
||||
|
||||
// Check if the pin is a GPIOHS pin.
|
||||
f := p.FPIOAFunction()
|
||||
if f < FUNC_GPIOHS0 || f > FUNC_GPIOHS31 {
|
||||
return ErrInvalidDataPin
|
||||
}
|
||||
|
||||
gpioPin := uint8(f - FUNC_GPIOHS0)
|
||||
|
||||
// Clear all interrupts.
|
||||
kendryte.GPIOHS.RISE_IE.ClearBits(1 << gpioPin)
|
||||
kendryte.GPIOHS.FALL_IE.ClearBits(1 << gpioPin)
|
||||
kendryte.GPIOHS.HIGH_IE.ClearBits(1 << gpioPin)
|
||||
kendryte.GPIOHS.LOW_IE.ClearBits(1 << gpioPin)
|
||||
|
||||
// Clear all the pending bits for this pin.
|
||||
kendryte.GPIOHS.RISE_IP.SetBits(1 << gpioPin)
|
||||
kendryte.GPIOHS.FALL_IP.SetBits(1 << gpioPin)
|
||||
kendryte.GPIOHS.HIGH_IP.SetBits(1 << gpioPin)
|
||||
kendryte.GPIOHS.LOW_IP.SetBits(1 << gpioPin)
|
||||
|
||||
if callback == nil {
|
||||
if pinCallbacks[gpioPin] != nil {
|
||||
pinCallbacks[gpioPin] = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if pinCallbacks[gpioPin] != nil {
|
||||
// The pin was already configured.
|
||||
// To properly re-configure a pin, unset it first and set a new
|
||||
// configuration.
|
||||
return ErrNoPinChangeChannel
|
||||
}
|
||||
|
||||
pinCallbacks[gpioPin] = callback
|
||||
|
||||
// Enable interrupts.
|
||||
if change&PinRising != 0 {
|
||||
kendryte.GPIOHS.RISE_IE.SetBits(1 << gpioPin)
|
||||
}
|
||||
if change&PinFalling != 0 {
|
||||
kendryte.GPIOHS.FALL_IE.SetBits(1 << gpioPin)
|
||||
}
|
||||
|
||||
handleInterrupt := func(inter interrupt.Interrupt) {
|
||||
|
||||
pin := uint8(inter.GetNumber() - kendryte.IRQ_GPIOHS0)
|
||||
|
||||
if kendryte.GPIOHS.RISE_IE.HasBits(1 << pin) {
|
||||
kendryte.GPIOHS.RISE_IE.ClearBits(1 << pin)
|
||||
// Acknowledge interrupt atomically.
|
||||
riscv.AsmFull(
|
||||
"amoor.w {}, {mask}, {reg}",
|
||||
map[string]interface{}{
|
||||
"mask": uint32(1 << pin),
|
||||
"reg": &kendryte.GPIOHS.RISE_IP.Reg,
|
||||
})
|
||||
kendryte.GPIOHS.RISE_IE.SetBits(1 << pin)
|
||||
}
|
||||
|
||||
if kendryte.GPIOHS.FALL_IE.HasBits(1 << pin) {
|
||||
kendryte.GPIOHS.FALL_IE.ClearBits(1 << pin)
|
||||
// Acknowledge interrupt atomically.
|
||||
riscv.AsmFull(
|
||||
"amoor.w {}, {mask}, {reg}",
|
||||
map[string]interface{}{
|
||||
"mask": uint32(1 << pin),
|
||||
"reg": &kendryte.GPIOHS.FALL_IP.Reg,
|
||||
})
|
||||
kendryte.GPIOHS.FALL_IE.SetBits(1 << pin)
|
||||
}
|
||||
|
||||
pinCallbacks[pin](Pin(pin))
|
||||
}
|
||||
|
||||
var ir interrupt.Interrupt
|
||||
|
||||
switch f {
|
||||
case FUNC_GPIOHS0:
|
||||
ir = interrupt.New(kendryte.IRQ_GPIOHS0, handleInterrupt)
|
||||
case FUNC_GPIOHS1:
|
||||
ir = interrupt.New(kendryte.IRQ_GPIOHS1, handleInterrupt)
|
||||
case FUNC_GPIOHS2:
|
||||
ir = interrupt.New(kendryte.IRQ_GPIOHS2, handleInterrupt)
|
||||
case FUNC_GPIOHS3:
|
||||
ir = interrupt.New(kendryte.IRQ_GPIOHS3, handleInterrupt)
|
||||
case FUNC_GPIOHS4:
|
||||
ir = interrupt.New(kendryte.IRQ_GPIOHS4, handleInterrupt)
|
||||
case FUNC_GPIOHS5:
|
||||
ir = interrupt.New(kendryte.IRQ_GPIOHS5, handleInterrupt)
|
||||
case FUNC_GPIOHS6:
|
||||
ir = interrupt.New(kendryte.IRQ_GPIOHS6, handleInterrupt)
|
||||
case FUNC_GPIOHS7:
|
||||
ir = interrupt.New(kendryte.IRQ_GPIOHS7, handleInterrupt)
|
||||
case FUNC_GPIOHS8:
|
||||
ir = interrupt.New(kendryte.IRQ_GPIOHS8, handleInterrupt)
|
||||
case FUNC_GPIOHS9:
|
||||
ir = interrupt.New(kendryte.IRQ_GPIOHS9, handleInterrupt)
|
||||
case FUNC_GPIOHS10:
|
||||
ir = interrupt.New(kendryte.IRQ_GPIOHS10, handleInterrupt)
|
||||
case FUNC_GPIOHS11:
|
||||
ir = interrupt.New(kendryte.IRQ_GPIOHS11, handleInterrupt)
|
||||
case FUNC_GPIOHS12:
|
||||
ir = interrupt.New(kendryte.IRQ_GPIOHS12, handleInterrupt)
|
||||
case FUNC_GPIOHS13:
|
||||
ir = interrupt.New(kendryte.IRQ_GPIOHS13, handleInterrupt)
|
||||
case FUNC_GPIOHS14:
|
||||
ir = interrupt.New(kendryte.IRQ_GPIOHS14, handleInterrupt)
|
||||
case FUNC_GPIOHS15:
|
||||
ir = interrupt.New(kendryte.IRQ_GPIOHS15, handleInterrupt)
|
||||
case FUNC_GPIOHS16:
|
||||
ir = interrupt.New(kendryte.IRQ_GPIOHS16, handleInterrupt)
|
||||
case FUNC_GPIOHS17:
|
||||
ir = interrupt.New(kendryte.IRQ_GPIOHS17, handleInterrupt)
|
||||
case FUNC_GPIOHS18:
|
||||
ir = interrupt.New(kendryte.IRQ_GPIOHS18, handleInterrupt)
|
||||
case FUNC_GPIOHS19:
|
||||
ir = interrupt.New(kendryte.IRQ_GPIOHS19, handleInterrupt)
|
||||
case FUNC_GPIOHS20:
|
||||
ir = interrupt.New(kendryte.IRQ_GPIOHS20, handleInterrupt)
|
||||
case FUNC_GPIOHS21:
|
||||
ir = interrupt.New(kendryte.IRQ_GPIOHS21, handleInterrupt)
|
||||
case FUNC_GPIOHS22:
|
||||
ir = interrupt.New(kendryte.IRQ_GPIOHS22, handleInterrupt)
|
||||
case FUNC_GPIOHS23:
|
||||
ir = interrupt.New(kendryte.IRQ_GPIOHS23, handleInterrupt)
|
||||
case FUNC_GPIOHS24:
|
||||
ir = interrupt.New(kendryte.IRQ_GPIOHS24, handleInterrupt)
|
||||
case FUNC_GPIOHS25:
|
||||
ir = interrupt.New(kendryte.IRQ_GPIOHS25, handleInterrupt)
|
||||
case FUNC_GPIOHS26:
|
||||
ir = interrupt.New(kendryte.IRQ_GPIOHS26, handleInterrupt)
|
||||
case FUNC_GPIOHS27:
|
||||
ir = interrupt.New(kendryte.IRQ_GPIOHS27, handleInterrupt)
|
||||
case FUNC_GPIOHS28:
|
||||
ir = interrupt.New(kendryte.IRQ_GPIOHS28, handleInterrupt)
|
||||
case FUNC_GPIOHS29:
|
||||
ir = interrupt.New(kendryte.IRQ_GPIOHS29, handleInterrupt)
|
||||
case FUNC_GPIOHS30:
|
||||
ir = interrupt.New(kendryte.IRQ_GPIOHS30, handleInterrupt)
|
||||
case FUNC_GPIOHS31:
|
||||
ir = interrupt.New(kendryte.IRQ_GPIOHS31, handleInterrupt)
|
||||
}
|
||||
|
||||
ir.SetPriority(5)
|
||||
ir.Enable()
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
type UART struct {
|
||||
Bus *kendryte.UARTHS_Type
|
||||
Buffer *RingBuffer
|
||||
}
|
||||
|
||||
var (
|
||||
UART0 = UART{Bus: kendryte.UARTHS, Buffer: NewRingBuffer()}
|
||||
)
|
||||
|
||||
func (uart UART) Configure(config UARTConfig) {
|
||||
|
||||
// Use default baudrate if not set.
|
||||
if config.BaudRate == 0 {
|
||||
config.BaudRate = 115200
|
||||
}
|
||||
|
||||
// Use default pins if not set.
|
||||
if config.TX == 0 && config.RX == 0 {
|
||||
config.TX = UART_TX_PIN
|
||||
config.RX = UART_RX_PIN
|
||||
}
|
||||
|
||||
config.TX.SetFPIOAFunction(FUNC_UARTHS_TX)
|
||||
config.RX.SetFPIOAFunction(FUNC_UARTHS_RX)
|
||||
|
||||
div := CPUFrequency()/config.BaudRate - 1
|
||||
|
||||
uart.Bus.DIV.Set(div)
|
||||
uart.Bus.TXCTRL.Set(kendryte.UARTHS_TXCTRL_TXEN)
|
||||
uart.Bus.RXCTRL.Set(kendryte.UARTHS_RXCTRL_RXEN)
|
||||
|
||||
// Enable interrupts on receive.
|
||||
uart.Bus.IE.Set(kendryte.UARTHS_IE_RXWM)
|
||||
|
||||
intr := interrupt.New(kendryte.IRQ_UARTHS, UART0.handleInterrupt)
|
||||
intr.SetPriority(5)
|
||||
intr.Enable()
|
||||
}
|
||||
|
||||
func (uart *UART) handleInterrupt(interrupt.Interrupt) {
|
||||
rxdata := uart.Bus.RXDATA.Get()
|
||||
c := byte(rxdata)
|
||||
if uint32(c) != rxdata {
|
||||
// The rxdata has other bits set than just the low 8 bits. This probably
|
||||
// means that the 'empty' flag is set, which indicates there is no data
|
||||
// to be read and the byte is garbage. Ignore this byte.
|
||||
return
|
||||
}
|
||||
uart.Receive(c)
|
||||
}
|
||||
|
||||
func (uart UART) WriteByte(c byte) {
|
||||
for uart.Bus.TXDATA.Get()&kendryte.UARTHS_TXDATA_FULL != 0 {
|
||||
}
|
||||
|
||||
uart.Bus.TXDATA.Set(uint32(c))
|
||||
}
|
||||
|
||||
type SPI struct {
|
||||
Bus *kendryte.SPI_Type
|
||||
}
|
||||
|
||||
// SPIConfig is used to store config info for SPI.
|
||||
type SPIConfig struct {
|
||||
Frequency uint32
|
||||
SCK Pin
|
||||
SDO Pin
|
||||
SDI Pin
|
||||
LSBFirst bool
|
||||
Mode uint8
|
||||
}
|
||||
|
||||
// Configure is intended to setup the SPI interface.
|
||||
// Only SPI controller 0 and 1 can be used because SPI2 is a special
|
||||
// peripheral-mode controller and SPI3 is used for flashing.
|
||||
func (spi SPI) Configure(config SPIConfig) error {
|
||||
// Use default pins if not set.
|
||||
if config.SCK == 0 && config.SDO == 0 && config.SDI == 0 {
|
||||
config.SCK = SPI0_SCK_PIN
|
||||
config.SDO = SPI0_SDO_PIN
|
||||
config.SDI = SPI0_SDI_PIN
|
||||
}
|
||||
|
||||
// Enable APB2 clock.
|
||||
kendryte.SYSCTL.CLK_EN_CENT.SetBits(kendryte.SYSCTL_CLK_EN_CENT_APB2_CLK_EN)
|
||||
|
||||
switch spi.Bus {
|
||||
case kendryte.SPI0:
|
||||
// Initialize SPI clock.
|
||||
kendryte.SYSCTL.CLK_EN_PERI.SetBits(kendryte.SYSCTL_CLK_EN_PERI_SPI0_CLK_EN)
|
||||
kendryte.SYSCTL.CLK_TH1.ClearBits(kendryte.SYSCTL_CLK_TH1_SPI0_CLK_Msk)
|
||||
|
||||
// Initialize pins.
|
||||
config.SCK.SetFPIOAFunction(FUNC_SPI0_SCLK)
|
||||
config.SDO.SetFPIOAFunction(FUNC_SPI0_D0)
|
||||
config.SDI.SetFPIOAFunction(FUNC_SPI0_D1)
|
||||
case kendryte.SPI1:
|
||||
// Initialize SPI clock.
|
||||
kendryte.SYSCTL.CLK_EN_PERI.SetBits(kendryte.SYSCTL_CLK_EN_PERI_SPI1_CLK_EN)
|
||||
kendryte.SYSCTL.CLK_TH1.ClearBits(kendryte.SYSCTL_CLK_TH1_SPI1_CLK_Msk)
|
||||
|
||||
// Initialize pins.
|
||||
config.SCK.SetFPIOAFunction(FUNC_SPI1_SCLK)
|
||||
config.SDO.SetFPIOAFunction(FUNC_SPI1_D0)
|
||||
config.SDI.SetFPIOAFunction(FUNC_SPI1_D1)
|
||||
default:
|
||||
return errUnsupportedSPIController
|
||||
}
|
||||
|
||||
// Set default frequency.
|
||||
if config.Frequency == 0 {
|
||||
config.Frequency = 500000
|
||||
}
|
||||
|
||||
baudr := CPUFrequency() / config.Frequency
|
||||
spi.Bus.BAUDR.Set(baudr)
|
||||
|
||||
// Configure SPI mode 0, standard frame format, 8-bit data, little-endian.
|
||||
spi.Bus.IMR.Set(0)
|
||||
spi.Bus.DMACR.Set(0)
|
||||
spi.Bus.DMATDLR.Set(0x10)
|
||||
spi.Bus.DMARDLR.Set(0)
|
||||
spi.Bus.SER.Set(0)
|
||||
spi.Bus.SSIENR.Set(0)
|
||||
spi.Bus.CTRLR0.Set((7 << 16))
|
||||
spi.Bus.SPI_CTRLR0.Set(0)
|
||||
spi.Bus.ENDIAN.Set(0)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Transfer writes/reads a single byte using the SPI interface.
|
||||
func (spi SPI) Transfer(w byte) (byte, error) {
|
||||
spi.Bus.SSIENR.Set(0)
|
||||
|
||||
// Set transfer-receive mode.
|
||||
spi.Bus.CTRLR0.ClearBits(0x3 << 8)
|
||||
|
||||
// Enable/disable SPI.
|
||||
spi.Bus.SSIENR.Set(1)
|
||||
defer spi.Bus.SSIENR.Set(0)
|
||||
|
||||
// Enable/disable device.
|
||||
spi.Bus.SER.Set(0x1)
|
||||
defer spi.Bus.SER.Set(0)
|
||||
|
||||
spi.Bus.DR0.Set(uint32(w))
|
||||
|
||||
// Wait for transfer.
|
||||
for spi.Bus.SR.Get()&0x05 != 0x04 {
|
||||
}
|
||||
|
||||
// Wait for data.
|
||||
for spi.Bus.RXFLR.Get() == 0 {
|
||||
}
|
||||
|
||||
return byte(spi.Bus.DR0.Get()), nil
|
||||
}
|
||||
|
||||
// I2C on the K210.
|
||||
type I2C struct {
|
||||
Bus *kendryte.I2C_Type
|
||||
}
|
||||
|
||||
// I2CConfig is used to store config info for I2C.
|
||||
type I2CConfig struct {
|
||||
Frequency uint32
|
||||
SCL Pin
|
||||
SDA Pin
|
||||
}
|
||||
|
||||
// Configure is intended to setup the I2C interface.
|
||||
func (i2c I2C) Configure(config I2CConfig) error {
|
||||
|
||||
if config.Frequency == 0 {
|
||||
config.Frequency = TWI_FREQ_100KHZ
|
||||
}
|
||||
|
||||
if config.SDA == 0 && config.SCL == 0 {
|
||||
config.SDA = I2C0_SDA_PIN
|
||||
config.SCL = I2C0_SCL_PIN
|
||||
}
|
||||
|
||||
// Enable APB0 clock.
|
||||
kendryte.SYSCTL.CLK_EN_CENT.SetBits(kendryte.SYSCTL_CLK_EN_CENT_APB0_CLK_EN)
|
||||
|
||||
switch i2c.Bus {
|
||||
case kendryte.I2C0:
|
||||
// Initialize I2C0 clock.
|
||||
kendryte.SYSCTL.CLK_EN_PERI.SetBits(kendryte.SYSCTL_CLK_EN_PERI_I2C0_CLK_EN)
|
||||
kendryte.SYSCTL.CLK_TH5.ReplaceBits(0x03, kendryte.SYSCTL_CLK_TH5_I2C0_CLK_Msk, kendryte.SYSCTL_CLK_TH5_I2C0_CLK_Pos)
|
||||
|
||||
// Initialize pins.
|
||||
config.SDA.SetFPIOAFunction(FUNC_I2C0_SDA)
|
||||
config.SCL.SetFPIOAFunction(FUNC_I2C0_SCLK)
|
||||
case kendryte.I2C1:
|
||||
// Initialize I2C1 clock.
|
||||
kendryte.SYSCTL.CLK_EN_PERI.SetBits(kendryte.SYSCTL_CLK_EN_PERI_I2C1_CLK_EN)
|
||||
kendryte.SYSCTL.CLK_TH5.ReplaceBits(0x03, kendryte.SYSCTL_CLK_TH5_I2C1_CLK_Msk, kendryte.SYSCTL_CLK_TH5_I2C1_CLK_Pos)
|
||||
|
||||
// Initialize pins.
|
||||
config.SDA.SetFPIOAFunction(FUNC_I2C1_SDA)
|
||||
config.SCL.SetFPIOAFunction(FUNC_I2C1_SCLK)
|
||||
case kendryte.I2C2:
|
||||
// Initialize I2C2 clock.
|
||||
kendryte.SYSCTL.CLK_EN_PERI.SetBits(kendryte.SYSCTL_CLK_EN_PERI_I2C2_CLK_EN)
|
||||
kendryte.SYSCTL.CLK_TH5.ReplaceBits(0x03, kendryte.SYSCTL_CLK_TH5_I2C2_CLK_Msk, kendryte.SYSCTL_CLK_TH5_I2C2_CLK_Pos)
|
||||
|
||||
// Initialize pins.
|
||||
config.SDA.SetFPIOAFunction(FUNC_I2C2_SDA)
|
||||
config.SCL.SetFPIOAFunction(FUNC_I2C2_SCLK)
|
||||
}
|
||||
|
||||
div := CPUFrequency() / config.Frequency / 16
|
||||
|
||||
// Disable controller before setting the prescale register.
|
||||
i2c.Bus.ENABLE.Set(0)
|
||||
|
||||
i2c.Bus.CON.Set(0x63)
|
||||
|
||||
// Set prescaler registers.
|
||||
i2c.Bus.SS_SCL_HCNT.Set(uint32(div))
|
||||
i2c.Bus.SS_SCL_LCNT.Set(uint32(div))
|
||||
|
||||
i2c.Bus.INTR_MASK.Set(0)
|
||||
i2c.Bus.DMA_CR.Set(0x03)
|
||||
i2c.Bus.DMA_RDLR.Set(0)
|
||||
i2c.Bus.DMA_TDLR.Set(0x4)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Tx does a single I2C transaction at the specified address.
|
||||
// It clocks out the given address, writes the bytes in w, reads back len(r)
|
||||
// bytes and stores them in r, and generates a stop condition on the bus.
|
||||
func (i2c I2C) Tx(addr uint16, w, r []byte) error {
|
||||
// Set peripheral address.
|
||||
i2c.Bus.TAR.Set(uint32(addr))
|
||||
// Enable controller.
|
||||
i2c.Bus.ENABLE.Set(1)
|
||||
|
||||
if len(w) != 0 {
|
||||
i2c.Bus.CLR_TX_ABRT.Set(i2c.Bus.CLR_TX_ABRT.Get())
|
||||
dataLen := uint32(len(w))
|
||||
di := 0
|
||||
|
||||
for dataLen != 0 {
|
||||
fifoLen := 8 - i2c.Bus.TXFLR.Get()
|
||||
if dataLen < fifoLen {
|
||||
fifoLen = dataLen
|
||||
}
|
||||
|
||||
for i := uint32(0); i < fifoLen; i++ {
|
||||
i2c.Bus.DATA_CMD.Set(uint32(w[di]))
|
||||
di += 1
|
||||
}
|
||||
if i2c.Bus.TX_ABRT_SOURCE.Get() != 0 {
|
||||
return errI2CTxAbort
|
||||
}
|
||||
dataLen -= fifoLen
|
||||
}
|
||||
|
||||
// Wait for transmition to complete.
|
||||
for i2c.Bus.STATUS.HasBits(kendryte.I2C_STATUS_ACTIVITY) || !i2c.Bus.STATUS.HasBits(kendryte.I2C_STATUS_TFE) {
|
||||
}
|
||||
|
||||
if i2c.Bus.TX_ABRT_SOURCE.Get() != 0 {
|
||||
return errI2CTxAbort
|
||||
}
|
||||
}
|
||||
if len(r) != 0 {
|
||||
dataLen := uint32(len(r))
|
||||
cmdLen := uint32(len(r))
|
||||
di := 0
|
||||
|
||||
for dataLen != 0 || cmdLen != 0 {
|
||||
fifoLen := i2c.Bus.RXFLR.Get()
|
||||
if dataLen < fifoLen {
|
||||
fifoLen = dataLen
|
||||
}
|
||||
for i := uint32(0); i < fifoLen; i++ {
|
||||
r[di] = byte(i2c.Bus.DATA_CMD.Get())
|
||||
di += 1
|
||||
}
|
||||
dataLen -= fifoLen
|
||||
|
||||
fifoLen = 8 - i2c.Bus.TXFLR.Get()
|
||||
if cmdLen < fifoLen {
|
||||
fifoLen = cmdLen
|
||||
}
|
||||
for i := uint32(0); i < fifoLen; i++ {
|
||||
i2c.Bus.DATA_CMD.Set(0x100)
|
||||
}
|
||||
if i2c.Bus.TX_ABRT_SOURCE.Get() != 0 {
|
||||
return errI2CTxAbort
|
||||
}
|
||||
cmdLen -= fifoLen
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -325,8 +325,8 @@ var (
|
||||
type SPIConfig struct {
|
||||
Frequency uint32
|
||||
SCK Pin
|
||||
MOSI Pin
|
||||
MISO Pin
|
||||
SDO Pin
|
||||
SDI Pin
|
||||
LSBFirst bool
|
||||
Mode uint8
|
||||
}
|
||||
@@ -387,7 +387,7 @@ func (spi SPI) Configure(config SPIConfig) {
|
||||
spi.Bus.CONFIG.Set(conf)
|
||||
|
||||
// set pins
|
||||
spi.setPins(config.SCK, config.MOSI, config.MISO)
|
||||
spi.setPins(config.SCK, config.SDO, config.SDI)
|
||||
|
||||
// Re-enable bus now that it is configured.
|
||||
spi.Bus.ENABLE.Set(nrf.SPI_ENABLE_ENABLE_Enabled)
|
||||
|
||||
@@ -30,17 +30,17 @@ func (i2c I2C) setPins(scl, sda Pin) {
|
||||
}
|
||||
|
||||
// SPI
|
||||
func (spi SPI) setPins(sck, mosi, miso Pin) {
|
||||
func (spi SPI) setPins(sck, sdo, sdi Pin) {
|
||||
if sck == 0 {
|
||||
sck = SPI0_SCK_PIN
|
||||
}
|
||||
if mosi == 0 {
|
||||
mosi = SPI0_MOSI_PIN
|
||||
if sdo == 0 {
|
||||
sdo = SPI0_SDO_PIN
|
||||
}
|
||||
if miso == 0 {
|
||||
miso = SPI0_MISO_PIN
|
||||
if sdi == 0 {
|
||||
sdi = SPI0_SDI_PIN
|
||||
}
|
||||
spi.Bus.PSELSCK.Set(uint32(sck))
|
||||
spi.Bus.PSELMOSI.Set(uint32(mosi))
|
||||
spi.Bus.PSELMISO.Set(uint32(miso))
|
||||
spi.Bus.PSELMOSI.Set(uint32(sdo))
|
||||
spi.Bus.PSELMISO.Set(uint32(sdi))
|
||||
}
|
||||
|
||||
@@ -31,19 +31,19 @@ func (i2c I2C) setPins(scl, sda Pin) {
|
||||
}
|
||||
|
||||
// SPI
|
||||
func (spi SPI) setPins(sck, mosi, miso Pin) {
|
||||
func (spi SPI) setPins(sck, sdo, sdi Pin) {
|
||||
if sck == 0 {
|
||||
sck = SPI0_SCK_PIN
|
||||
}
|
||||
if mosi == 0 {
|
||||
mosi = SPI0_MOSI_PIN
|
||||
if sdo == 0 {
|
||||
sdo = SPI0_SDO_PIN
|
||||
}
|
||||
if miso == 0 {
|
||||
miso = SPI0_MISO_PIN
|
||||
if sdi == 0 {
|
||||
sdi = SPI0_SDI_PIN
|
||||
}
|
||||
spi.Bus.PSEL.SCK.Set(uint32(sck))
|
||||
spi.Bus.PSEL.MOSI.Set(uint32(mosi))
|
||||
spi.Bus.PSEL.MISO.Set(uint32(miso))
|
||||
spi.Bus.PSEL.MOSI.Set(uint32(sdo))
|
||||
spi.Bus.PSEL.MISO.Set(uint32(sdi))
|
||||
}
|
||||
|
||||
// InitADC initializes the registers needed for ADC.
|
||||
|
||||
@@ -83,19 +83,19 @@ func (i2c I2C) setPins(scl, sda Pin) {
|
||||
}
|
||||
|
||||
// SPI
|
||||
func (spi SPI) setPins(sck, mosi, miso Pin) {
|
||||
func (spi SPI) setPins(sck, sdo, sdi Pin) {
|
||||
if sck == 0 {
|
||||
sck = SPI0_SCK_PIN
|
||||
}
|
||||
if mosi == 0 {
|
||||
mosi = SPI0_MOSI_PIN
|
||||
if sdo == 0 {
|
||||
sdo = SPI0_SDO_PIN
|
||||
}
|
||||
if miso == 0 {
|
||||
miso = SPI0_MISO_PIN
|
||||
if sdi == 0 {
|
||||
sdi = SPI0_SDI_PIN
|
||||
}
|
||||
spi.Bus.PSEL.SCK.Set(uint32(sck))
|
||||
spi.Bus.PSEL.MOSI.Set(uint32(mosi))
|
||||
spi.Bus.PSEL.MISO.Set(uint32(miso))
|
||||
spi.Bus.PSEL.MOSI.Set(uint32(sdo))
|
||||
spi.Bus.PSEL.MISO.Set(uint32(sdi))
|
||||
}
|
||||
|
||||
// InitADC initializes the registers needed for ADC.
|
||||
|
||||
@@ -0,0 +1,285 @@
|
||||
// Derivative work of Teensyduino Core Library
|
||||
// http://www.pjrc.com/teensy/
|
||||
// Copyright (c) 2017 PJRC.COM, LLC.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// 1. The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// 2. If the Software is incorporated into a build system that allows
|
||||
// selection among a list of target devices, then similar target
|
||||
// devices manufactured by PJRC.COM must be included in the list of
|
||||
// target devices and selectable in the same manner.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
// +build nxp,mk66f18
|
||||
|
||||
package machine
|
||||
|
||||
import (
|
||||
"device/nxp"
|
||||
"runtime/volatile"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type PinMode uint8
|
||||
|
||||
const (
|
||||
PinInput PinMode = iota
|
||||
PinInputPullUp
|
||||
PinInputPullDown
|
||||
PinOutput
|
||||
PinOutputOpenDrain
|
||||
PinDisable
|
||||
)
|
||||
|
||||
const (
|
||||
PA00 Pin = iota
|
||||
PA01
|
||||
PA02
|
||||
PA03
|
||||
PA04
|
||||
PA05
|
||||
PA06
|
||||
PA07
|
||||
PA08
|
||||
PA09
|
||||
PA10
|
||||
PA11
|
||||
PA12
|
||||
PA13
|
||||
PA14
|
||||
PA15
|
||||
PA16
|
||||
PA17
|
||||
PA18
|
||||
PA19
|
||||
PA20
|
||||
PA21
|
||||
PA22
|
||||
PA23
|
||||
PA24
|
||||
PA25
|
||||
PA26
|
||||
PA27
|
||||
PA28
|
||||
PA29
|
||||
)
|
||||
|
||||
const (
|
||||
PB00 Pin = iota + 32
|
||||
PB01
|
||||
PB02
|
||||
PB03
|
||||
PB04
|
||||
PB05
|
||||
PB06
|
||||
PB07
|
||||
PB08
|
||||
PB09
|
||||
PB10
|
||||
PB11
|
||||
_
|
||||
_
|
||||
_
|
||||
_
|
||||
PB16
|
||||
PB17
|
||||
PB18
|
||||
PB19
|
||||
PB20
|
||||
PB21
|
||||
PB22
|
||||
PB23
|
||||
)
|
||||
|
||||
const (
|
||||
PC00 Pin = iota + 64
|
||||
PC01
|
||||
PC02
|
||||
PC03
|
||||
PC04
|
||||
PC05
|
||||
PC06
|
||||
PC07
|
||||
PC08
|
||||
PC09
|
||||
PC10
|
||||
PC11
|
||||
PC12
|
||||
PC13
|
||||
PC14
|
||||
PC15
|
||||
PC16
|
||||
PC17
|
||||
PC18
|
||||
PC19
|
||||
)
|
||||
|
||||
const (
|
||||
PD00 Pin = iota + 96
|
||||
PD01
|
||||
PD02
|
||||
PD03
|
||||
PD04
|
||||
PD05
|
||||
PD06
|
||||
PD07
|
||||
PD08
|
||||
PD09
|
||||
PD10
|
||||
PD11
|
||||
PD12
|
||||
PD13
|
||||
PD14
|
||||
PD15
|
||||
)
|
||||
|
||||
const (
|
||||
PE00 Pin = iota + 128
|
||||
PE01
|
||||
PE02
|
||||
PE03
|
||||
PE04
|
||||
PE05
|
||||
PE06
|
||||
PE07
|
||||
PE08
|
||||
PE09
|
||||
PE10
|
||||
PE11
|
||||
PE12
|
||||
PE13
|
||||
PE14
|
||||
PE15
|
||||
PE16
|
||||
PE17
|
||||
PE18
|
||||
PE19
|
||||
PE20
|
||||
PE21
|
||||
PE22
|
||||
PE23
|
||||
PE24
|
||||
PE25
|
||||
PE26
|
||||
PE27
|
||||
PE28
|
||||
)
|
||||
|
||||
//go:inline
|
||||
func (p Pin) reg() (*nxp.GPIO_Type, *volatile.Register32, uint8) {
|
||||
var gpio *nxp.GPIO_Type
|
||||
var pcr *nxp.PORT_Type
|
||||
|
||||
switch p / 32 {
|
||||
case 0:
|
||||
gpio, pcr = nxp.GPIOA, nxp.PORTA
|
||||
case 1:
|
||||
gpio, pcr = nxp.GPIOB, nxp.PORTB
|
||||
case 2:
|
||||
gpio, pcr = nxp.GPIOC, nxp.PORTC
|
||||
case 3:
|
||||
gpio, pcr = nxp.GPIOD, nxp.PORTD
|
||||
case 5:
|
||||
gpio, pcr = nxp.GPIOE, nxp.PORTE
|
||||
default:
|
||||
panic("invalid pin number")
|
||||
}
|
||||
|
||||
return gpio, &(*[32]volatile.Register32)(unsafe.Pointer(pcr))[p%32], uint8(p % 32)
|
||||
}
|
||||
|
||||
// Configure this pin with the given configuration.
|
||||
func (p Pin) Configure(config PinConfig) {
|
||||
gpio, pcr, pos := p.reg()
|
||||
|
||||
switch config.Mode {
|
||||
case PinOutput:
|
||||
gpio.PDDR.SetBits(1 << pos)
|
||||
pcr.Set((1 << nxp.PORT_PCR0_MUX_Pos) | nxp.PORT_PCR0_SRE | nxp.PORT_PCR0_DSE)
|
||||
|
||||
case PinOutputOpenDrain:
|
||||
gpio.PDDR.SetBits(1 << pos)
|
||||
pcr.Set((1 << nxp.PORT_PCR0_MUX_Pos) | nxp.PORT_PCR0_SRE | nxp.PORT_PCR0_DSE | nxp.PORT_PCR0_ODE)
|
||||
|
||||
case PinInput:
|
||||
gpio.PDDR.ClearBits(1 << pos)
|
||||
pcr.Set((1 << nxp.PORT_PCR0_MUX_Pos))
|
||||
|
||||
case PinInputPullUp:
|
||||
gpio.PDDR.ClearBits(1 << pos)
|
||||
pcr.Set((1 << nxp.PORT_PCR0_MUX_Pos) | nxp.PORT_PCR0_PE | nxp.PORT_PCR0_PS)
|
||||
|
||||
case PinInputPullDown:
|
||||
gpio.PDDR.ClearBits(1 << pos)
|
||||
pcr.Set((1 << nxp.PORT_PCR0_MUX_Pos) | nxp.PORT_PCR0_PE)
|
||||
|
||||
case PinDisable:
|
||||
gpio.PDDR.ClearBits(1 << pos)
|
||||
pcr.Set((0 << nxp.PORT_PCR0_MUX_Pos))
|
||||
}
|
||||
}
|
||||
|
||||
// Set changes the value of the GPIO pin. The pin must be configured as output.
|
||||
func (p Pin) Set(value bool) {
|
||||
gpio, _, pos := p.reg()
|
||||
if value {
|
||||
gpio.PSOR.Set(1 << pos)
|
||||
} else {
|
||||
gpio.PCOR.Set(1 << pos)
|
||||
}
|
||||
}
|
||||
|
||||
// Get returns the current value of a GPIO pin.
|
||||
func (p Pin) Get() bool {
|
||||
gpio, _, pos := p.reg()
|
||||
return gpio.PDIR.HasBits(1 << pos)
|
||||
}
|
||||
|
||||
func (p Pin) Control() *volatile.Register32 {
|
||||
_, pcr, _ := p.reg()
|
||||
return pcr
|
||||
}
|
||||
|
||||
func (p Pin) Fast() FastPin {
|
||||
gpio, _, pos := p.reg()
|
||||
return FastPin{
|
||||
PDOR: gpio.PDOR.Bit(pos),
|
||||
PSOR: gpio.PSOR.Bit(pos),
|
||||
PCOR: gpio.PCOR.Bit(pos),
|
||||
PTOR: gpio.PTOR.Bit(pos),
|
||||
PDIR: gpio.PDIR.Bit(pos),
|
||||
PDDR: gpio.PDDR.Bit(pos),
|
||||
}
|
||||
}
|
||||
|
||||
type FastPin struct {
|
||||
PDOR *volatile.BitRegister
|
||||
PSOR *volatile.BitRegister
|
||||
PCOR *volatile.BitRegister
|
||||
PTOR *volatile.BitRegister
|
||||
PDIR *volatile.BitRegister
|
||||
PDDR *volatile.BitRegister
|
||||
}
|
||||
|
||||
func (p FastPin) Set() { p.PSOR.Set(true) }
|
||||
func (p FastPin) Clear() { p.PCOR.Set(true) }
|
||||
func (p FastPin) Toggle() { p.PTOR.Set(true) }
|
||||
func (p FastPin) Write(v bool) { p.PDOR.Set(v) }
|
||||
func (p FastPin) Read() bool { return p.PDIR.Get() }
|
||||
@@ -27,9 +27,9 @@ const (
|
||||
PinModeI2CSDA PinMode = 7
|
||||
|
||||
// for SPI
|
||||
PinModeSPICLK PinMode = 8
|
||||
PinModeSPIMOSI PinMode = 9
|
||||
PinModeSPIMISO PinMode = 10
|
||||
PinModeSPICLK PinMode = 8
|
||||
PinModeSPISDO PinMode = 9
|
||||
PinModeSPISDI PinMode = 10
|
||||
|
||||
// for analog/ADC
|
||||
PinInputAnalog PinMode = 11
|
||||
@@ -102,12 +102,12 @@ func (p Pin) ConfigureAltFunc(config PinConfig, altFunc stm32.AltFunc) {
|
||||
port.OSPEEDR.ReplaceBits(stm32.GPIOSpeedLow, 0x3, pos)
|
||||
port.PUPDR.ReplaceBits(stm32.GPIOPUPDRFloating, 0x3, pos)
|
||||
p.SetAltFunc(altFunc)
|
||||
case PinModeSPIMOSI:
|
||||
case PinModeSPISDO:
|
||||
port.MODER.ReplaceBits(stm32.GPIOModeOutputAltFunc, 0x3, pos)
|
||||
port.OSPEEDR.ReplaceBits(stm32.GPIOSpeedLow, 0x3, pos)
|
||||
port.PUPDR.ReplaceBits(stm32.GPIOPUPDRFloating, 0x3, pos)
|
||||
p.SetAltFunc(altFunc)
|
||||
case PinModeSPIMISO:
|
||||
case PinModeSPISDI:
|
||||
port.MODER.ReplaceBits(stm32.GPIOModeOutputAltFunc, 0x3, pos)
|
||||
port.OSPEEDR.ReplaceBits(stm32.GPIOSpeedLow, 0x3, pos)
|
||||
port.PUPDR.ReplaceBits(stm32.GPIOPUPDRFloating, 0x3, pos)
|
||||
|
||||
@@ -13,8 +13,8 @@ import (
|
||||
type SPIConfig struct {
|
||||
Frequency uint32
|
||||
SCK Pin
|
||||
MOSI Pin
|
||||
MISO Pin
|
||||
SDO Pin
|
||||
SDI Pin
|
||||
LSBFirst bool
|
||||
Mode uint8
|
||||
}
|
||||
@@ -56,20 +56,20 @@ func (spi SPI) Configure(config SPIConfig) {
|
||||
conf &^= (1 << stm32.SPI_CR1_CPHA_Pos)
|
||||
}
|
||||
|
||||
// set to SPI master
|
||||
// set to SPI controller
|
||||
conf |= stm32.SPI_CR1_MSTR
|
||||
|
||||
// disable MCU acting as SPI slave
|
||||
// disable MCU acting as SPI peripheral
|
||||
conf |= stm32.SPI_CR1_SSM | stm32.SPI_CR1_SSI
|
||||
|
||||
// now set the configuration
|
||||
spi.Bus.CR1.Set(conf)
|
||||
|
||||
// init pins
|
||||
if config.SCK == 0 && config.MOSI == 0 && config.MISO == 0 {
|
||||
if config.SCK == 0 && config.SDO == 0 && config.SDI == 0 {
|
||||
config.SCK = SPI0_SCK_PIN
|
||||
config.MOSI = SPI0_MOSI_PIN
|
||||
config.MISO = SPI0_MISO_PIN
|
||||
config.SDO = SPI0_SDO_PIN
|
||||
config.SDI = SPI0_SDI_PIN
|
||||
}
|
||||
spi.configurePins(config)
|
||||
|
||||
|
||||
@@ -191,8 +191,8 @@ func (spi SPI) getBaudRate(config SPIConfig) uint32 {
|
||||
// Configure SPI pins for input output and clock
|
||||
func (spi SPI) configurePins(config SPIConfig) {
|
||||
config.SCK.Configure(PinConfig{Mode: PinOutput50MHz + PinOutputModeAltPushPull})
|
||||
config.MOSI.Configure(PinConfig{Mode: PinOutput50MHz + PinOutputModeAltPushPull})
|
||||
config.MISO.Configure(PinConfig{Mode: PinInputModeFloating})
|
||||
config.SDO.Configure(PinConfig{Mode: PinOutput50MHz + PinOutputModeAltPushPull})
|
||||
config.SDI.Configure(PinConfig{Mode: PinInputModeFloating})
|
||||
}
|
||||
|
||||
//---------- I2C related types and code
|
||||
|
||||
@@ -164,6 +164,6 @@ func (spi SPI) getBaudRate(config SPIConfig) uint32 {
|
||||
// Configure SPI pins for input output and clock
|
||||
func (spi SPI) configurePins(config SPIConfig) {
|
||||
config.SCK.ConfigureAltFunc(PinConfig{Mode: PinModeSPICLK}, spi.AltFuncSelector)
|
||||
config.MOSI.ConfigureAltFunc(PinConfig{Mode: PinModeSPIMOSI}, spi.AltFuncSelector)
|
||||
config.MISO.ConfigureAltFunc(PinConfig{Mode: PinModeSPIMISO}, spi.AltFuncSelector)
|
||||
config.SDO.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDO}, spi.AltFuncSelector)
|
||||
config.SDI.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDI}, spi.AltFuncSelector)
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// +build !baremetal sam stm32 fe310
|
||||
// +build !baremetal sam stm32 fe310 k210
|
||||
|
||||
package machine
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// +build avr nrf sam sifive stm32
|
||||
// +build avr nrf sam sifive stm32 k210 nxp
|
||||
|
||||
package machine
|
||||
|
||||
|
||||
@@ -0,0 +1,305 @@
|
||||
// Derivative work of Teensyduino Core Library
|
||||
// http://www.pjrc.com/teensy/
|
||||
// Copyright (c) 2017 PJRC.COM, LLC.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// 1. The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// 2. If the Software is incorporated into a build system that allows
|
||||
// selection among a list of target devices, then similar target
|
||||
// devices manufactured by PJRC.COM must be included in the list of
|
||||
// target devices and selectable in the same manner.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
// +build nxp,mk66f18
|
||||
|
||||
package machine
|
||||
|
||||
import (
|
||||
"device/arm"
|
||||
"device/nxp"
|
||||
"errors"
|
||||
"runtime/interrupt"
|
||||
"runtime/volatile"
|
||||
|
||||
_ "unsafe" // for go:linkname
|
||||
)
|
||||
|
||||
const (
|
||||
uartC2Enable = nxp.UART_C2_TE | nxp.UART_C2_RE | nxp.UART_C2_RIE | nxp.UART_C2_ILIE
|
||||
uartC2TXActive = uartC2Enable | nxp.UART_C2_TIE
|
||||
uartC2TXCompleting = uartC2Enable | nxp.UART_C2_TCIE
|
||||
uartC2TXInactive = uartC2Enable
|
||||
|
||||
uartIRQPriority = 64
|
||||
|
||||
// determined from UARTx_PFIFO
|
||||
uartRXFIFODepth = 8
|
||||
uartTXFIFODepth = 8
|
||||
)
|
||||
|
||||
var (
|
||||
ErrNotImplemented = errors.New("device has not been implemented")
|
||||
ErrNotConfigured = errors.New("device has not been configured")
|
||||
)
|
||||
|
||||
//go:linkname gosched runtime.Gosched
|
||||
func gosched()
|
||||
|
||||
// PutcharUART writes a byte to the UART synchronously, without using interrupts
|
||||
// or calling the scheduler
|
||||
func PutcharUART(u UART, c byte) {
|
||||
// ensure the UART has been configured
|
||||
if !u.SCGC.HasBits(u.SCGCMask) {
|
||||
u.configure(UARTConfig{}, false)
|
||||
}
|
||||
|
||||
for u.TCFIFO.Get() > 0 {
|
||||
// busy wait
|
||||
}
|
||||
u.D.Set(c)
|
||||
u.C2.Set(uartC2TXActive)
|
||||
}
|
||||
|
||||
// PollUART manually checks a UART status and calls the ISR. This should only be
|
||||
// called by runtime.abort.
|
||||
func PollUART(u UART) {
|
||||
if u.SCGC.HasBits(u.SCGCMask) {
|
||||
u.handleStatusInterrupt(u.Interrupt)
|
||||
}
|
||||
}
|
||||
|
||||
type UART = *UARTData
|
||||
|
||||
type UARTData struct {
|
||||
*nxp.UART_Type
|
||||
SCGC *volatile.Register32
|
||||
SCGCMask uint32
|
||||
|
||||
DefaultRX Pin
|
||||
DefaultTX Pin
|
||||
|
||||
// state
|
||||
Buffer RingBuffer // RX Buffer
|
||||
TXBuffer RingBuffer
|
||||
Configured bool
|
||||
Transmitting volatile.Register8
|
||||
Interrupt interrupt.Interrupt
|
||||
}
|
||||
|
||||
var UART0 = UARTData{UART_Type: nxp.UART0, SCGC: &nxp.SIM.SCGC4, SCGCMask: nxp.SIM_SCGC4_UART0, DefaultRX: defaultUART0RX, DefaultTX: defaultUART0TX}
|
||||
var UART1 = UARTData{UART_Type: nxp.UART1, SCGC: &nxp.SIM.SCGC4, SCGCMask: nxp.SIM_SCGC4_UART1, DefaultRX: defaultUART1RX, DefaultTX: defaultUART1TX}
|
||||
var UART2 = UARTData{UART_Type: nxp.UART2, SCGC: &nxp.SIM.SCGC4, SCGCMask: nxp.SIM_SCGC4_UART2, DefaultRX: defaultUART2RX, DefaultTX: defaultUART2TX}
|
||||
var UART3 = UARTData{UART_Type: nxp.UART3, SCGC: &nxp.SIM.SCGC4, SCGCMask: nxp.SIM_SCGC4_UART3, DefaultRX: defaultUART3RX, DefaultTX: defaultUART3TX}
|
||||
var UART4 = UARTData{UART_Type: nxp.UART4, SCGC: &nxp.SIM.SCGC1, SCGCMask: nxp.SIM_SCGC1_UART4, DefaultRX: defaultUART4RX, DefaultTX: defaultUART4TX}
|
||||
|
||||
func init() {
|
||||
UART0.Interrupt = interrupt.New(nxp.IRQ_UART0_RX_TX, UART0.handleStatusInterrupt)
|
||||
UART1.Interrupt = interrupt.New(nxp.IRQ_UART1_RX_TX, UART1.handleStatusInterrupt)
|
||||
UART2.Interrupt = interrupt.New(nxp.IRQ_UART2_RX_TX, UART2.handleStatusInterrupt)
|
||||
UART3.Interrupt = interrupt.New(nxp.IRQ_UART3_RX_TX, UART3.handleStatusInterrupt)
|
||||
UART4.Interrupt = interrupt.New(nxp.IRQ_UART4_RX_TX, UART4.handleStatusInterrupt)
|
||||
}
|
||||
|
||||
// Configure the UART.
|
||||
func (u UART) Configure(config UARTConfig) {
|
||||
u.configure(config, true)
|
||||
}
|
||||
|
||||
func (u UART) configure(config UARTConfig, canSched bool) {
|
||||
// from: serial_begin
|
||||
|
||||
if !u.Configured {
|
||||
u.Transmitting.Set(0)
|
||||
|
||||
// turn on the clock
|
||||
u.SCGC.Set(u.SCGCMask)
|
||||
|
||||
// configure pins
|
||||
u.DefaultRX.Control().Set(nxp.PORT_PCR0_PE | nxp.PORT_PCR0_PS | nxp.PORT_PCR0_PFE | (3 << nxp.PORT_PCR0_MUX_Pos))
|
||||
u.DefaultTX.Control().Set(nxp.PORT_PCR0_DSE | nxp.PORT_PCR0_SRE | (3 << nxp.PORT_PCR0_MUX_Pos))
|
||||
u.C1.Set(nxp.UART_C1_ILT)
|
||||
}
|
||||
|
||||
// default to 115200 baud
|
||||
if config.BaudRate == 0 {
|
||||
config.BaudRate = 115200
|
||||
}
|
||||
|
||||
// copied from teensy core's BAUD2DIV macro
|
||||
divisor := ((CPUFrequency() * 2) + (config.BaudRate >> 1)) / config.BaudRate
|
||||
if divisor < 32 {
|
||||
divisor = 32
|
||||
}
|
||||
|
||||
if u.Configured {
|
||||
// don't change baud rate mid transmit
|
||||
if canSched {
|
||||
u.Flush()
|
||||
} else {
|
||||
for u.Transmitting.Get() != 0 {
|
||||
// busy wait flush
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// set the divisor
|
||||
u.BDH.Set(uint8((divisor >> 13) & 0x1F))
|
||||
u.BDL.Set(uint8((divisor >> 5) & 0xFF))
|
||||
u.C4.Set(uint8(divisor & 0x1F))
|
||||
|
||||
if !u.Configured {
|
||||
u.Configured = true
|
||||
|
||||
u.C1.Set(nxp.UART_C1_ILT)
|
||||
|
||||
// configure TX and RX watermark
|
||||
u.TWFIFO.Set(2) // causes bit TDRE of S1 to set
|
||||
u.RWFIFO.Set(4) // causes bit RDRF of S1 to set
|
||||
|
||||
// enable FIFOs
|
||||
u.PFIFO.Set(nxp.UART_PFIFO_TXFE | nxp.UART_PFIFO_RXFE)
|
||||
|
||||
// setup interrupts
|
||||
u.C2.Set(uartC2TXInactive)
|
||||
u.Interrupt.SetPriority(uartIRQPriority)
|
||||
u.Interrupt.Enable()
|
||||
}
|
||||
}
|
||||
|
||||
func (u UART) Disable() {
|
||||
// from: serial_end
|
||||
|
||||
// check if the device has been enabled already
|
||||
if !u.SCGC.HasBits(u.SCGCMask) {
|
||||
return
|
||||
}
|
||||
|
||||
u.Flush()
|
||||
|
||||
u.Interrupt.Disable()
|
||||
u.C2.Set(0)
|
||||
|
||||
// reconfigure pin
|
||||
u.DefaultRX.Configure(PinConfig{Mode: PinInputPullUp})
|
||||
u.DefaultTX.Configure(PinConfig{Mode: PinInputPullUp})
|
||||
|
||||
// clear flags
|
||||
u.S1.Get()
|
||||
u.D.Get()
|
||||
u.Buffer.Clear()
|
||||
}
|
||||
|
||||
func (u UART) Flush() {
|
||||
for u.Transmitting.Get() != 0 {
|
||||
gosched()
|
||||
}
|
||||
}
|
||||
|
||||
func (u UART) handleStatusInterrupt(interrupt.Interrupt) {
|
||||
// from: uart0_status_isr
|
||||
|
||||
// receive
|
||||
if u.S1.HasBits(nxp.UART_S1_RDRF | nxp.UART_S1_IDLE) {
|
||||
intrs := arm.DisableInterrupts()
|
||||
avail := u.RCFIFO.Get()
|
||||
if avail == 0 {
|
||||
// The only way to clear the IDLE interrupt flag is
|
||||
// to read the data register. But reading with no
|
||||
// data causes a FIFO underrun, which causes the
|
||||
// FIFO to return corrupted data. If anyone from
|
||||
// Freescale reads this, what a poor design! There
|
||||
// write should be a write-1-to-clear for IDLE.
|
||||
u.D.Get()
|
||||
// flushing the fifo recovers from the underrun,
|
||||
// but there's a possible race condition where a
|
||||
// new character could be received between reading
|
||||
// RCFIFO == 0 and flushing the FIFO. To minimize
|
||||
// the chance, interrupts are disabled so a higher
|
||||
// priority interrupt (hopefully) doesn't delay.
|
||||
// TODO: change this to disabling the IDLE interrupt
|
||||
// which won't be simple, since we already manage
|
||||
// which transmit interrupts are enabled.
|
||||
u.CFIFO.Set(nxp.UART_CFIFO_RXFLUSH)
|
||||
arm.EnableInterrupts(intrs)
|
||||
|
||||
} else {
|
||||
arm.EnableInterrupts(intrs)
|
||||
|
||||
for {
|
||||
u.Buffer.Put(u.D.Get())
|
||||
avail--
|
||||
if avail <= 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// transmit
|
||||
if u.C2.HasBits(nxp.UART_C2_TIE) && u.S1.HasBits(nxp.UART_S1_TDRE) {
|
||||
data := make([]byte, 0, uartTXFIFODepth)
|
||||
avail := uartTXFIFODepth - u.TCFIFO.Get()
|
||||
|
||||
// get avail bytes from ring buffer
|
||||
for len(data) < int(avail) {
|
||||
if b, ok := u.TXBuffer.Get(); ok {
|
||||
data = append(data, b)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// write data to FIFO
|
||||
l := len(data)
|
||||
for i, b := range data {
|
||||
if i == l-1 {
|
||||
// only clear TDRE on last write, per the manual
|
||||
u.S1.Get()
|
||||
}
|
||||
u.D.Set(b)
|
||||
}
|
||||
|
||||
// if FIFO still has room, disable TIE, enable TCIE
|
||||
if u.S1.HasBits(nxp.UART_S1_TDRE) {
|
||||
u.C2.Set(uartC2TXCompleting)
|
||||
}
|
||||
}
|
||||
|
||||
// transmit complete
|
||||
if u.C2.HasBits(nxp.UART_C2_TCIE) && u.S1.HasBits(nxp.UART_S1_TC) {
|
||||
u.Transmitting.Set(0)
|
||||
u.C2.Set(uartC2TXInactive)
|
||||
}
|
||||
}
|
||||
|
||||
// WriteByte writes a byte of data to the UART.
|
||||
func (u UART) WriteByte(c byte) error {
|
||||
if !u.Configured {
|
||||
return ErrNotConfigured
|
||||
}
|
||||
|
||||
for !u.TXBuffer.Put(c) {
|
||||
gosched()
|
||||
}
|
||||
|
||||
u.Transmitting.Set(1)
|
||||
u.C2.Set(uartC2TXActive)
|
||||
return nil
|
||||
}
|
||||
@@ -102,3 +102,7 @@ func procPin() {
|
||||
func procUnpin() {
|
||||
arm.EnableInterrupts(procPinnedMask)
|
||||
}
|
||||
|
||||
func waitForEvents() {
|
||||
arm.Asm("wfe")
|
||||
}
|
||||
|
||||
@@ -4,16 +4,6 @@ package runtime
|
||||
|
||||
import "device/riscv"
|
||||
|
||||
const GOARCH = "arm" // riscv pretends to be arm
|
||||
|
||||
// The bitness of the CPU (e.g. 8, 32, 64).
|
||||
const TargetBits = 32
|
||||
|
||||
// Align on word boundary.
|
||||
func align(ptr uintptr) uintptr {
|
||||
return (ptr + 3) &^ 3
|
||||
}
|
||||
|
||||
func getCurrentStackPointer() uintptr {
|
||||
return riscv.AsmFull("mv {}, sp", nil)
|
||||
}
|
||||
@@ -90,3 +80,11 @@ func procPin() {
|
||||
func procUnpin() {
|
||||
riscv.EnableInterrupts(procPinnedMask)
|
||||
}
|
||||
|
||||
func waitForEvents() {
|
||||
mask := riscv.DisableInterrupts()
|
||||
if !runqueue.Empty() {
|
||||
riscv.Asm("wfi")
|
||||
}
|
||||
riscv.EnableInterrupts(mask)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
// +build tinygo.riscv32
|
||||
|
||||
package runtime
|
||||
|
||||
const GOARCH = "arm" // riscv pretends to be arm
|
||||
|
||||
// The bitness of the CPU (e.g. 8, 32, 64).
|
||||
const TargetBits = 32
|
||||
|
||||
// Align on word boundary.
|
||||
func align(ptr uintptr) uintptr {
|
||||
return (ptr + 3) &^ 3
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// +build tinygo.riscv64
|
||||
|
||||
package runtime
|
||||
|
||||
const GOARCH = "arm64" // riscv pretends to be arm
|
||||
|
||||
// The bitness of the CPU (e.g. 8, 32, 64).
|
||||
const TargetBits = 64
|
||||
|
||||
// Align on word boundary.
|
||||
func align(ptr uintptr) uintptr {
|
||||
return (ptr + 7) &^ 7
|
||||
}
|
||||
@@ -38,3 +38,5 @@ func libc_malloc(size uintptr) unsafe.Pointer {
|
||||
func libc_free(ptr unsafe.Pointer) {
|
||||
free(ptr)
|
||||
}
|
||||
|
||||
const baremetal = true
|
||||
|
||||
@@ -25,6 +25,7 @@ package runtime
|
||||
|
||||
import (
|
||||
"internal/task"
|
||||
"runtime/interrupt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
@@ -308,13 +309,17 @@ func (ch *channel) trySend(value unsafe.Pointer) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
i := interrupt.Disable()
|
||||
|
||||
switch ch.state {
|
||||
case chanStateEmpty, chanStateBuf:
|
||||
// try to dump the value directly into the buffer
|
||||
if ch.push(value) {
|
||||
ch.state = chanStateBuf
|
||||
interrupt.Restore(i)
|
||||
return true
|
||||
}
|
||||
interrupt.Restore(i)
|
||||
return false
|
||||
case chanStateRecv:
|
||||
// unblock reciever
|
||||
@@ -328,16 +333,21 @@ func (ch *channel) trySend(value unsafe.Pointer) bool {
|
||||
ch.state = chanStateEmpty
|
||||
}
|
||||
|
||||
interrupt.Restore(i)
|
||||
return true
|
||||
case chanStateSend:
|
||||
// something else is already waiting to send
|
||||
interrupt.Restore(i)
|
||||
return false
|
||||
case chanStateClosed:
|
||||
interrupt.Restore(i)
|
||||
runtimePanic("send on closed channel")
|
||||
default:
|
||||
interrupt.Restore(i)
|
||||
runtimePanic("invalid channel state")
|
||||
}
|
||||
|
||||
interrupt.Restore(i)
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -351,6 +361,8 @@ func (ch *channel) tryRecv(value unsafe.Pointer) (bool, bool) {
|
||||
return false, false
|
||||
}
|
||||
|
||||
i := interrupt.Disable()
|
||||
|
||||
switch ch.state {
|
||||
case chanStateBuf, chanStateSend:
|
||||
// try to pop the value directly from the buffer
|
||||
@@ -373,6 +385,7 @@ func (ch *channel) tryRecv(value unsafe.Pointer) (bool, bool) {
|
||||
ch.state = chanStateEmpty
|
||||
}
|
||||
|
||||
interrupt.Restore(i)
|
||||
return true, true
|
||||
} else if ch.blocked != nil {
|
||||
// unblock next sender if applicable
|
||||
@@ -386,19 +399,24 @@ func (ch *channel) tryRecv(value unsafe.Pointer) (bool, bool) {
|
||||
ch.state = chanStateEmpty
|
||||
}
|
||||
|
||||
interrupt.Restore(i)
|
||||
return true, true
|
||||
}
|
||||
interrupt.Restore(i)
|
||||
return false, false
|
||||
case chanStateRecv, chanStateEmpty:
|
||||
// something else is already waiting to recieve
|
||||
interrupt.Restore(i)
|
||||
return false, false
|
||||
case chanStateClosed:
|
||||
if ch.pop(value) {
|
||||
interrupt.Restore(i)
|
||||
return true, true
|
||||
}
|
||||
|
||||
// channel closed - nothing to recieve
|
||||
memzero(value, ch.elementSize)
|
||||
interrupt.Restore(i)
|
||||
return true, false
|
||||
default:
|
||||
runtimePanic("invalid channel state")
|
||||
@@ -447,14 +465,18 @@ type chanSelectState struct {
|
||||
// This operation will block unless a value is immediately available.
|
||||
// May panic if the channel is closed.
|
||||
func chanSend(ch *channel, value unsafe.Pointer, blockedlist *channelBlockedList) {
|
||||
i := interrupt.Disable()
|
||||
|
||||
if ch.trySend(value) {
|
||||
// value immediately sent
|
||||
chanDebug(ch)
|
||||
interrupt.Restore(i)
|
||||
return
|
||||
}
|
||||
|
||||
if ch == nil {
|
||||
// A nil channel blocks forever. Do not schedule this goroutine again.
|
||||
interrupt.Restore(i)
|
||||
deadlock()
|
||||
}
|
||||
|
||||
@@ -468,6 +490,7 @@ func chanSend(ch *channel, value unsafe.Pointer, blockedlist *channelBlockedList
|
||||
}
|
||||
ch.blocked = blockedlist
|
||||
chanDebug(ch)
|
||||
interrupt.Restore(i)
|
||||
task.Pause()
|
||||
sender.Ptr = nil
|
||||
}
|
||||
@@ -477,14 +500,18 @@ func chanSend(ch *channel, value unsafe.Pointer, blockedlist *channelBlockedList
|
||||
// The recieved value is copied into the value pointer.
|
||||
// Returns the comma-ok value.
|
||||
func chanRecv(ch *channel, value unsafe.Pointer, blockedlist *channelBlockedList) bool {
|
||||
i := interrupt.Disable()
|
||||
|
||||
if rx, ok := ch.tryRecv(value); rx {
|
||||
// value immediately available
|
||||
chanDebug(ch)
|
||||
interrupt.Restore(i)
|
||||
return ok
|
||||
}
|
||||
|
||||
if ch == nil {
|
||||
// A nil channel blocks forever. Do not schedule this goroutine again.
|
||||
interrupt.Restore(i)
|
||||
deadlock()
|
||||
}
|
||||
|
||||
@@ -498,6 +525,7 @@ func chanRecv(ch *channel, value unsafe.Pointer, blockedlist *channelBlockedList
|
||||
}
|
||||
ch.blocked = blockedlist
|
||||
chanDebug(ch)
|
||||
interrupt.Restore(i)
|
||||
task.Pause()
|
||||
ok := receiver.Data == 1
|
||||
receiver.Ptr, receiver.Data = nil, 0
|
||||
@@ -511,15 +539,18 @@ func chanClose(ch *channel) {
|
||||
// Not allowed by the language spec.
|
||||
runtimePanic("close of nil channel")
|
||||
}
|
||||
i := interrupt.Disable()
|
||||
switch ch.state {
|
||||
case chanStateClosed:
|
||||
// Not allowed by the language spec.
|
||||
interrupt.Restore(i)
|
||||
runtimePanic("close of closed channel")
|
||||
case chanStateSend:
|
||||
// This panic should ideally on the sending side, not in this goroutine.
|
||||
// But when a goroutine tries to send while the channel is being closed,
|
||||
// that is clearly invalid: the send should have been completed already
|
||||
// before the close.
|
||||
interrupt.Restore(i)
|
||||
runtimePanic("close channel during send")
|
||||
case chanStateRecv:
|
||||
// unblock all receivers with the zero value
|
||||
@@ -531,6 +562,7 @@ func chanClose(ch *channel) {
|
||||
// Easy case. No available sender or receiver.
|
||||
}
|
||||
ch.state = chanStateClosed
|
||||
interrupt.Restore(i)
|
||||
chanDebug(ch)
|
||||
}
|
||||
|
||||
@@ -541,8 +573,11 @@ func chanClose(ch *channel) {
|
||||
// TODO: do this in a round-robin fashion (as specified in the Go spec) instead
|
||||
// of picking the first one that can proceed.
|
||||
func chanSelect(recvbuf unsafe.Pointer, states []chanSelectState, ops []channelBlockedList) (uintptr, bool) {
|
||||
istate := interrupt.Disable()
|
||||
|
||||
if selected, ok := tryChanSelect(recvbuf, states); selected != ^uintptr(0) {
|
||||
// one channel was immediately ready
|
||||
interrupt.Restore(istate)
|
||||
return selected, ok
|
||||
}
|
||||
|
||||
@@ -570,6 +605,7 @@ func chanSelect(recvbuf unsafe.Pointer, states []chanSelectState, ops []channelB
|
||||
case chanStateRecv:
|
||||
// already in correct state
|
||||
default:
|
||||
interrupt.Restore(istate)
|
||||
runtimePanic("invalid channel state")
|
||||
}
|
||||
} else {
|
||||
@@ -582,6 +618,7 @@ func chanSelect(recvbuf unsafe.Pointer, states []chanSelectState, ops []channelB
|
||||
case chanStateBuf:
|
||||
// already in correct state
|
||||
default:
|
||||
interrupt.Restore(istate)
|
||||
runtimePanic("invalid channel state")
|
||||
}
|
||||
}
|
||||
@@ -594,6 +631,7 @@ func chanSelect(recvbuf unsafe.Pointer, states []chanSelectState, ops []channelB
|
||||
t.Data = 1
|
||||
|
||||
// wait for one case to fire
|
||||
interrupt.Restore(istate)
|
||||
task.Pause()
|
||||
|
||||
// figure out which one fired and return the ok value
|
||||
@@ -602,22 +640,27 @@ func chanSelect(recvbuf unsafe.Pointer, states []chanSelectState, ops []channelB
|
||||
|
||||
// tryChanSelect is like chanSelect, but it does a non-blocking select operation.
|
||||
func tryChanSelect(recvbuf unsafe.Pointer, states []chanSelectState) (uintptr, bool) {
|
||||
istate := interrupt.Disable()
|
||||
|
||||
// See whether we can receive from one of the channels.
|
||||
for i, state := range states {
|
||||
if state.value == nil {
|
||||
// A receive operation.
|
||||
if rx, ok := state.ch.tryRecv(recvbuf); rx {
|
||||
chanDebug(state.ch)
|
||||
interrupt.Restore(istate)
|
||||
return uintptr(i), ok
|
||||
}
|
||||
} else {
|
||||
// A send operation: state.value is not nil.
|
||||
if state.ch.trySend(state.value) {
|
||||
chanDebug(state.ch)
|
||||
interrupt.Restore(istate)
|
||||
return uintptr(i), true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interrupt.Restore(istate)
|
||||
return ^uintptr(0), false
|
||||
}
|
||||
|
||||
@@ -29,6 +29,8 @@ package runtime
|
||||
// Moss.
|
||||
|
||||
import (
|
||||
"internal/task"
|
||||
"runtime/interrupt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
@@ -292,9 +294,39 @@ func GC() {
|
||||
}
|
||||
|
||||
// Mark phase: mark all reachable objects, recursively.
|
||||
markGlobals()
|
||||
markStack()
|
||||
finishMark()
|
||||
markGlobals()
|
||||
|
||||
if baremetal && hasScheduler {
|
||||
// Channel operations in interrupts may move task pointers around while we are marking.
|
||||
// Therefore we need to scan the runqueue seperately.
|
||||
var markedTaskQueue task.Queue
|
||||
runqueueScan:
|
||||
for !runqueue.Empty() {
|
||||
// Pop the next task off of the runqueue.
|
||||
t := runqueue.Pop()
|
||||
|
||||
// Mark the task if it has not already been marked.
|
||||
markRoot(uintptr(unsafe.Pointer(&runqueue)), uintptr(unsafe.Pointer(t)))
|
||||
|
||||
// Push the task onto our temporary queue.
|
||||
markedTaskQueue.Push(t)
|
||||
}
|
||||
|
||||
finishMark()
|
||||
|
||||
// Restore the runqueue.
|
||||
i := interrupt.Disable()
|
||||
if !runqueue.Empty() {
|
||||
// Something new came in while finishing the mark.
|
||||
interrupt.Restore(i)
|
||||
goto runqueueScan
|
||||
}
|
||||
runqueue = markedTaskQueue
|
||||
interrupt.Restore(i)
|
||||
} else {
|
||||
finishMark()
|
||||
}
|
||||
|
||||
// Sweep phase: free all non-marked objects and unmark marked objects for
|
||||
// the next collection cycle.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user