mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-07-30 08:38:41 +00:00
Compare commits
73 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 15361c829e | |||
| 3f680b75f3 | |||
| 9a7e633997 | |||
| 39b1f8b6f5 | |||
| 9aa50853b8 | |||
| 9ca0e3f2d1 | |||
| 3cdc110462 | |||
| 7cc687d416 | |||
| ce57a034c3 | |||
| 30bee3afef | |||
| b1d24a72c1 | |||
| 6e24c86320 | |||
| 19a0270303 | |||
| 47410a4b54 | |||
| 0d9c46b59e | |||
| f93b28057a | |||
| 691185f5f4 | |||
| 163df7670a | |||
| 77c70d2758 | |||
| 7c4e83f5c0 | |||
| db27541b1a | |||
| 3bb994da9f | |||
| b3bd891ee0 | |||
| 387bca8e32 | |||
| d424b3d7ea | |||
| c20328472b | |||
| 171f793c1e | |||
| 3364da6f25 | |||
| e99b8a24fe | |||
| 69e1aa4878 | |||
| 7a78b2dc0e | |||
| 2b1d4ce96e | |||
| 3e40b08ba0 | |||
| ffeff55706 | |||
| 1dec9dcbc4 | |||
| ff833ef998 | |||
| 6eeebfeb5c | |||
| 6ab0106af3 | |||
| e690ff0d8c | |||
| 06564cbdb2 | |||
| 47dc76fc34 | |||
| d382f3a259 | |||
| 47dc1087e8 | |||
| c7d8223ab7 | |||
| 3eb33dff5d | |||
| bb146edb47 | |||
| ed9b97cc0d | |||
| b40f250530 | |||
| 184175378f | |||
| d8dbe5748a | |||
| c2bfe6bc8d | |||
| 9a015f4f64 | |||
| 9ad2315079 | |||
| 431e51b8a0 | |||
| 67de8b490d | |||
| bfa29f17da | |||
| 7123941df0 | |||
| 05d2f2c412 | |||
| 9a12d129ab | |||
| 0ecfe9eade | |||
| f50ad3585d | |||
| d39c7abb4d | |||
| 9e61e6fe4d | |||
| d1f90ef59c | |||
| 54602fe0c3 | |||
| c10dcd429c | |||
| b713001313 | |||
| 1096596b69 | |||
| 7b601b3e3c | |||
| ec54e7763d | |||
| 41afb77080 | |||
| 13fe668929 | |||
| 2a72262c33 |
+16
-5
@@ -28,6 +28,7 @@ commands:
|
||||
qemu-user \
|
||||
gcc-avr \
|
||||
avr-libc
|
||||
sudo apt-get install --no-install-recommends libc6-dev-i386 lib32gcc-8-dev
|
||||
install-node:
|
||||
steps:
|
||||
- run:
|
||||
@@ -44,6 +45,13 @@ commands:
|
||||
command: |
|
||||
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
|
||||
sudo apt install ./google-chrome-stable_current_amd64.deb
|
||||
install-wasmtime:
|
||||
steps:
|
||||
- run:
|
||||
name: "Install wasmtime"
|
||||
command: |
|
||||
curl https://wasmtime.dev/install.sh -sSf | bash
|
||||
sudo ln -s ~/.wasmtime/bin/wasmtime /usr/local/bin/wasmtime
|
||||
install-xtensa-toolchain:
|
||||
parameters:
|
||||
variant:
|
||||
@@ -91,6 +99,7 @@ commands:
|
||||
llvm: "<<parameters.llvm>>"
|
||||
- install-node
|
||||
- install-chrome
|
||||
- install-wasmtime
|
||||
- restore_cache:
|
||||
keys:
|
||||
- go-cache-v2-{{ checksum "go.mod" }}-{{ .Environment.CIRCLE_PREVIOUS_BUILD_NUM }}
|
||||
@@ -125,7 +134,6 @@ commands:
|
||||
command: |
|
||||
sudo apt-get install \
|
||||
gcc-arm-linux-gnueabihf \
|
||||
binutils-arm-none-eabi \
|
||||
libc6-dev-armel-cross \
|
||||
gcc-aarch64-linux-gnu \
|
||||
libc6-dev-arm64-cross \
|
||||
@@ -133,7 +141,9 @@ commands:
|
||||
qemu-user \
|
||||
gcc-avr \
|
||||
avr-libc
|
||||
sudo apt-get install --no-install-recommends libc6-dev-i386 lib32gcc-6-dev
|
||||
- install-node
|
||||
- install-wasmtime
|
||||
- install-xtensa-toolchain:
|
||||
variant: "linux-amd64"
|
||||
- restore_cache:
|
||||
@@ -185,7 +195,6 @@ commands:
|
||||
command: |
|
||||
sudo apt-get install \
|
||||
gcc-arm-linux-gnueabihf \
|
||||
binutils-arm-none-eabi \
|
||||
libc6-dev-armel-cross \
|
||||
gcc-aarch64-linux-gnu \
|
||||
libc6-dev-arm64-cross \
|
||||
@@ -193,7 +202,9 @@ commands:
|
||||
qemu-user \
|
||||
gcc-avr \
|
||||
avr-libc
|
||||
sudo apt-get install --no-install-recommends libc6-dev-i386 lib32gcc-6-dev
|
||||
- install-node
|
||||
- install-wasmtime
|
||||
- install-xtensa-toolchain:
|
||||
variant: "linux-amd64"
|
||||
- restore_cache:
|
||||
@@ -413,12 +424,12 @@ jobs:
|
||||
steps:
|
||||
- test-linux:
|
||||
llvm: "10"
|
||||
test-llvm10-go115:
|
||||
test-llvm11-go115:
|
||||
docker:
|
||||
- image: circleci/golang:1.15-buster
|
||||
steps:
|
||||
- test-linux:
|
||||
llvm: "10"
|
||||
llvm: "11"
|
||||
assert-test-linux:
|
||||
docker:
|
||||
- image: circleci/golang:1.14-stretch
|
||||
@@ -450,7 +461,7 @@ workflows:
|
||||
- test-llvm10-go112
|
||||
- test-llvm10-go113
|
||||
- test-llvm10-go114
|
||||
- test-llvm10-go115
|
||||
- test-llvm11-go115
|
||||
- build-linux
|
||||
- build-macos
|
||||
- assert-test-linux
|
||||
|
||||
@@ -1,3 +1,57 @@
|
||||
0.16.0
|
||||
---
|
||||
|
||||
* **command-line**
|
||||
- add initial support for LLVM 11
|
||||
- make lib64 clang include path check more robust
|
||||
- `build`: improve support for GOARCH=386 and add tests
|
||||
- `gdb`: add support for qemu-user targets
|
||||
- `test`: support non-host tests
|
||||
- `test`: add support for -c and -o flags
|
||||
- `test`: implement some benchmark stubs
|
||||
* **compiler**
|
||||
- `builder`: improve detection of clang on Fedora
|
||||
- `compiler`: fix floating point comparison bugs
|
||||
- `compiler`: implement negate for complex numbers
|
||||
- `loader`: fix linkname in test binaries
|
||||
- `transform`: add missing return pointer restore for regular coroutine tail
|
||||
calls
|
||||
* **standard library**
|
||||
- `machine`: switch default frequency to 4MHz
|
||||
- `machine`: clarify caller's responsibility in `SetInterrupt`
|
||||
- `os`: add `LookupEnv()` stub
|
||||
- `reflect`: implement `Swapper`
|
||||
- `runtime`: fix UTF-8 decoding
|
||||
- `runtime`: gc: use raw stack access whenever possible
|
||||
- `runtime`: use dedicated printfloat32
|
||||
- `runtime`: allow ranging over a nil map
|
||||
- `runtime`: avoid device/nxp dependency in HardFault handler
|
||||
- `testing`: implement dummy Helper method
|
||||
- `testing`: add Run method
|
||||
* **targets**
|
||||
- `arm64`: add support for SVCall intrinsic
|
||||
- `atsamd51`: avoid panic when configuring SPI with SDI=NoPin
|
||||
- `avr`: properly support the `.rodata` section
|
||||
- `esp8266`: implement `Pin.Get` function
|
||||
- `nintendoswitch`: fix crash when printing long lines (> 120)
|
||||
- `nintendoswitch`: add env parser and removed unused stuff
|
||||
- `nrf`: add I2C error checking
|
||||
- `nrf`: give more flexibility in picking SPI speeds
|
||||
- `nrf`: fix nrf52832 flash size
|
||||
- `stm32f103`: support wakeups from interrupts
|
||||
- `stm32f405`: add SPI support
|
||||
- `stm32f405`: add I2C support
|
||||
- `wasi`: add support for this target
|
||||
- `wasi`: use 'generic' ABI by default
|
||||
- `wasi`: remove --no-threads flag from wasm-ld
|
||||
- `wasm`: add instanceof support for WebAssembly
|
||||
- `wasm`: use fixed length buffer for putchar
|
||||
* **boards**
|
||||
- `d1mini`: add this ESP8266 based board
|
||||
- `esp32`: use board definitions instead of chip names
|
||||
- `qtpy`: add board definition for Adafruit QTPy
|
||||
- `teensy40`: add this board
|
||||
|
||||
0.15.0
|
||||
---
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
# TinyGo base stage installs Go 1.14, LLVM 10 and the TinyGo compiler itself.
|
||||
FROM golang:1.14 AS tinygo-base
|
||||
# TinyGo base stage installs the most recent Go 1.15.x, LLVM 10 and the TinyGo compiler itself.
|
||||
FROM golang:1.15 AS tinygo-base
|
||||
|
||||
RUN wget -O- https://apt.llvm.org/llvm-snapshot.gpg.key| apt-key add - && \
|
||||
echo "deb http://apt.llvm.org/buster/ llvm-toolchain-buster-10 main" >> /etc/apt/sources.list && \
|
||||
|
||||
@@ -9,25 +9,10 @@ CLANG_SRC ?= $(LLVM_PROJECTDIR)/clang
|
||||
LLD_SRC ?= $(LLVM_PROJECTDIR)/lld
|
||||
|
||||
# Try to autodetect LLVM build tools.
|
||||
ifneq (, $(shell command -v llvm-build/bin/clang 2> /dev/null))
|
||||
CLANG ?= $(abspath llvm-build/bin/clang)
|
||||
else
|
||||
CLANG ?= clang-10
|
||||
endif
|
||||
ifneq (, $(shell command -v llvm-build/bin/llvm-ar 2> /dev/null))
|
||||
LLVM_AR ?= $(abspath llvm-build/bin/llvm-ar)
|
||||
else ifneq (, $(shell command -v llvm-ar-10 2> /dev/null))
|
||||
LLVM_AR ?= llvm-ar-10
|
||||
else
|
||||
LLVM_AR ?= llvm-ar
|
||||
endif
|
||||
ifneq (, $(shell command -v llvm-build/bin/llvm-nm 2> /dev/null))
|
||||
LLVM_NM ?= $(abspath llvm-build/bin/llvm-nm)
|
||||
else ifneq (, $(shell command -v llvm-nm-10 2> /dev/null))
|
||||
LLVM_NM ?= llvm-nm-10
|
||||
else
|
||||
LLVM_NM ?= llvm-nm
|
||||
endif
|
||||
detect = $(shell command -v $(1) 2> /dev/null && echo $(1))
|
||||
CLANG ?= $(word 1,$(abspath $(call detect,llvm-build/bin/clang))$(call detect,clang-11)$(call detect,clang-10)$(call detect,clang))
|
||||
LLVM_AR ?= $(word 1,$(abspath $(call detect,llvm-build/bin/llvm-ar))$(call detect,llvm-ar-11)$(call detect,llvm-ar-10)$(call detect,llvm-ar))
|
||||
LLVM_NM ?= $(word 1,$(abspath $(call detect,llvm-build/bin/llvm-nm))$(call detect,llvm-nm-11)$(call detect,llvm-nm-10)$(call detect,llvm-nm))
|
||||
|
||||
# Go binary and GOROOT to select
|
||||
GO ?= go
|
||||
@@ -37,7 +22,7 @@ export GOROOT = $(shell $(GO) env GOROOT)
|
||||
MD5SUM = md5sum
|
||||
|
||||
# tinygo binary for tests
|
||||
TINYGO ?= tinygo
|
||||
TINYGO ?= $(word 1,$(call detect,tinygo)$(call detect,build/tinygo))
|
||||
|
||||
# Use CCACHE for LLVM if possible
|
||||
ifneq (, $(shell command -v ccache 2> /dev/null))
|
||||
@@ -104,7 +89,7 @@ LLD_LIBS = $(START_GROUP) -llldCOFF -llldCommon -llldCore -llldDriver -llldELF -
|
||||
ifneq ("$(wildcard $(LLVM_BUILDDIR)/bin/llvm-config*)","")
|
||||
CGO_CPPFLAGS=$(shell $(LLVM_BUILDDIR)/bin/llvm-config --cppflags) -I$(abspath $(LLVM_BUILDDIR))/tools/clang/include -I$(abspath $(CLANG_SRC))/include -I$(abspath $(LLD_SRC))/include
|
||||
CGO_CXXFLAGS=-std=c++14
|
||||
CGO_LDFLAGS+=$(LIBCLANG_PATH) -std=c++14 -L$(abspath $(LLVM_BUILDDIR)/lib) $(CLANG_LIBS) $(LLD_LIBS) $(shell $(LLVM_BUILDDIR)/bin/llvm-config --ldflags --libs --system-libs $(LLVM_COMPONENTS)) -lstdc++ $(CGO_LDFLAGS_EXTRA)
|
||||
CGO_LDFLAGS+=$(LIBCLANG_PATH) -L$(abspath $(LLVM_BUILDDIR)/lib) $(CLANG_LIBS) $(LLD_LIBS) $(shell $(LLVM_BUILDDIR)/bin/llvm-config --ldflags --libs --system-libs $(LLVM_COMPONENTS)) -lstdc++ $(CGO_LDFLAGS_EXTRA)
|
||||
endif
|
||||
|
||||
|
||||
@@ -195,9 +180,18 @@ test: wasi-libc
|
||||
# implied -v flag).
|
||||
.PHONY: tinygo-test
|
||||
tinygo-test:
|
||||
$(TINYGO) test container/heap
|
||||
$(TINYGO) test container/list
|
||||
$(TINYGO) test container/ring
|
||||
$(TINYGO) test crypto/des
|
||||
$(TINYGO) test encoding/ascii85
|
||||
$(TINYGO) test encoding/base32
|
||||
$(TINYGO) test encoding/hex
|
||||
$(TINYGO) test hash/fnv
|
||||
$(TINYGO) test hash/crc64
|
||||
$(TINYGO) test math
|
||||
$(TINYGO) test text/scanner
|
||||
$(TINYGO) test unicode/utf8
|
||||
|
||||
.PHONY: smoketest
|
||||
smoketest:
|
||||
@@ -234,8 +228,6 @@ smoketest:
|
||||
# test simulated boards on play.tinygo.org
|
||||
$(TINYGO) build -o test.wasm -tags=arduino examples/blinky1
|
||||
@$(MD5SUM) test.wasm
|
||||
$(TINYGO) build -o test.wasm -tags=hifive1-qemu examples/serial
|
||||
@$(MD5SUM) test.wasm
|
||||
$(TINYGO) build -o test.wasm -tags=hifive1b examples/blinky1
|
||||
@$(MD5SUM) test.wasm
|
||||
$(TINYGO) build -o test.wasm -tags=reelboard examples/blinky1
|
||||
@@ -287,7 +279,7 @@ smoketest:
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=circuitplay-express examples/i2s
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=clue_alpha examples/blinky1
|
||||
$(TINYGO) build -size short -o test.hex -target=clue-alpha examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.gba -target=gameboy-advance examples/gba-display
|
||||
@$(MD5SUM) test.gba
|
||||
@@ -331,6 +323,12 @@ smoketest:
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=itsybitsy-nrf52840 examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=qtpy examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=teensy40 examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=teensy36 examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
# test pwm
|
||||
$(TINYGO) build -size short -o test.hex -target=itsybitsy-m0 examples/pwm
|
||||
@$(MD5SUM) test.hex
|
||||
@@ -357,13 +355,15 @@ ifneq ($(AVR), 0)
|
||||
@$(MD5SUM) test.hex
|
||||
endif
|
||||
ifneq ($(XTENSA), 0)
|
||||
$(TINYGO) build -size short -o test.bin -target=esp32-wroom-32 examples/blinky1
|
||||
$(TINYGO) build -size short -o test.bin -target=esp32-mini32 examples/blinky1
|
||||
@$(MD5SUM) test.bin
|
||||
$(TINYGO) build -size short -o test.bin -target=nodemcu examples/blinky1
|
||||
@$(MD5SUM) test.bin
|
||||
endif
|
||||
$(TINYGO) build -size short -o test.hex -target=hifive1b examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=hifive1-qemu examples/serial
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=maixbit examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -o wasm.wasm -target=wasm examples/wasm/export
|
||||
|
||||
+10
-11
@@ -79,7 +79,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
||||
// keep functions interoperable, pass int64 types as pointers to
|
||||
// stack-allocated values.
|
||||
// Use -wasm-abi=generic to disable this behaviour.
|
||||
if config.Options.WasmAbi == "js" && strings.HasPrefix(config.Triple(), "wasm") {
|
||||
if config.WasmAbi() == "js" {
|
||||
err := transform.ExternalInt64AsPtr(mod)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -117,16 +117,15 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
||||
return errors.New("verification failure after LLVM optimization passes")
|
||||
}
|
||||
|
||||
// On the AVR, pointers can point either to flash or to RAM, but we don't
|
||||
// know. As a temporary fix, load all global variables in RAM.
|
||||
// In the future, there should be a compiler pass that determines which
|
||||
// pointers are flash and which are in RAM so that pointers can have a
|
||||
// correct address space parameter (address space 1 is for flash).
|
||||
if strings.HasPrefix(config.Triple(), "avr") {
|
||||
transform.NonConstGlobals(mod)
|
||||
if err := llvm.VerifyModule(mod, llvm.PrintMessageAction); err != nil {
|
||||
return errors.New("verification error after making all globals non-constant on AVR")
|
||||
}
|
||||
// LLVM 11 by default tries to emit tail calls (even with the target feature
|
||||
// disabled) unless it is explicitly disabled with a function attribute.
|
||||
// This is a problem, as it tries to emit them and prints an error when it
|
||||
// can't with this feature disabled.
|
||||
// Because as of september 2020 tail calls are not yet widely supported,
|
||||
// they need to be disabled until they are widely supported (at which point
|
||||
// the +tail-call target feautre can be set).
|
||||
if strings.HasPrefix(config.Triple(), "wasm") {
|
||||
transform.DisableTailCalls(mod)
|
||||
}
|
||||
|
||||
// Make sure stack sizes are loaded from a separate section so they can be
|
||||
|
||||
+29
-9
@@ -6,6 +6,9 @@ import (
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"tinygo.org/x/go-llvm"
|
||||
)
|
||||
|
||||
// getClangHeaderPath returns the path to the built-in Clang headers. It tries
|
||||
@@ -26,6 +29,7 @@ func getClangHeaderPath(TINYGOROOT string) string {
|
||||
|
||||
// It looks like we are built with a system-installed LLVM. Do a last
|
||||
// attempt: try to use Clang headers relative to the clang binary.
|
||||
llvmMajor := strings.Split(llvm.Version, ".")[0]
|
||||
for _, cmdName := range commands["clang"] {
|
||||
binpath, err := exec.LookPath(cmdName)
|
||||
if err == nil {
|
||||
@@ -40,22 +44,38 @@ func getClangHeaderPath(TINYGOROOT string) string {
|
||||
// Example executable:
|
||||
// /usr/lib/llvm-9/bin/clang
|
||||
// Example include path:
|
||||
// /usr/lib/llvm-9/lib/clang/9.0.1/include/
|
||||
// /usr/lib/llvm-9/lib64/clang/9.0.1/include/
|
||||
llvmRoot := filepath.Dir(filepath.Dir(binpath))
|
||||
clangVersionRoot := filepath.Join(llvmRoot, "lib", "clang")
|
||||
dirs, err := ioutil.ReadDir(clangVersionRoot)
|
||||
if err != nil {
|
||||
clangVersionRoot := filepath.Join(llvmRoot, "lib64", "clang")
|
||||
dirs64, err64 := ioutil.ReadDir(clangVersionRoot)
|
||||
// Example include path:
|
||||
// /usr/lib/llvm-9/lib/clang/9.0.1/include/
|
||||
clangVersionRoot = filepath.Join(llvmRoot, "lib", "clang")
|
||||
dirs32, err32 := ioutil.ReadDir(clangVersionRoot)
|
||||
if err64 != nil && err32 != nil {
|
||||
// Unexpected.
|
||||
continue
|
||||
}
|
||||
dirnames := make([]string, len(dirs))
|
||||
for i, d := range dirs {
|
||||
dirnames[i] = d.Name()
|
||||
dirnames := make([]string, len(dirs64)+len(dirs32))
|
||||
dirCount := 0
|
||||
for _, d := range dirs32 {
|
||||
name := d.Name()
|
||||
if name == llvmMajor || strings.HasPrefix(name, llvmMajor+".") {
|
||||
dirnames[dirCount] = filepath.Join(llvmRoot, "lib", "clang", name)
|
||||
dirCount++
|
||||
}
|
||||
}
|
||||
for _, d := range dirs64 {
|
||||
name := d.Name()
|
||||
if name == llvmMajor || strings.HasPrefix(name, llvmMajor+".") {
|
||||
dirnames[dirCount] = filepath.Join(llvmRoot, "lib64", "clang", name)
|
||||
dirCount++
|
||||
}
|
||||
}
|
||||
sort.Strings(dirnames)
|
||||
// Check for the highest version first.
|
||||
for i := len(dirnames) - 1; i >= 0; i-- {
|
||||
path := filepath.Join(clangVersionRoot, dirnames[i], "include")
|
||||
for i := dirCount - 1; i >= 0; i-- {
|
||||
path := filepath.Join(dirnames[i], "include")
|
||||
_, err := os.Stat(filepath.Join(path, "stdint.h"))
|
||||
if err == nil {
|
||||
return path
|
||||
|
||||
+7
-1
@@ -61,7 +61,7 @@ func extractROM(path string) (uint64, []byte, error) {
|
||||
|
||||
progs := make(progSlice, 0, 2)
|
||||
for _, prog := range f.Progs {
|
||||
if prog.Type != elf.PT_LOAD || prog.Filesz == 0 {
|
||||
if prog.Type != elf.PT_LOAD || prog.Filesz == 0 || prog.Off == 0 {
|
||||
continue
|
||||
}
|
||||
progs = append(progs, prog)
|
||||
@@ -73,6 +73,12 @@ func extractROM(path string) (uint64, []byte, error) {
|
||||
|
||||
var rom []byte
|
||||
for _, prog := range progs {
|
||||
romEnd := progs[0].Paddr + uint64(len(rom))
|
||||
if prog.Paddr > romEnd && prog.Paddr < romEnd+16 {
|
||||
// Sometimes, the linker seems to insert a bit of padding between
|
||||
// segments. Simply zero-fill these parts.
|
||||
rom = append(rom, make([]byte, prog.Paddr-romEnd)...)
|
||||
}
|
||||
if prog.Paddr != progs[0].Paddr+uint64(len(rom)) {
|
||||
diff := prog.Paddr - (progs[0].Paddr + uint64(len(rom)))
|
||||
if diff > maxPadBytes {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// +build !byollvm
|
||||
// +build !llvm9
|
||||
// +build !llvm9,!llvm11
|
||||
|
||||
package cgo
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
// +build !byollvm
|
||||
// +build llvm11
|
||||
|
||||
package cgo
|
||||
|
||||
/*
|
||||
#cgo linux CFLAGS: -I/usr/lib/llvm-11/include
|
||||
#cgo darwin CFLAGS: -I/usr/local/opt/llvm@11/include
|
||||
#cgo freebsd CFLAGS: -I/usr/local/llvm11/include
|
||||
#cgo linux LDFLAGS: -L/usr/lib/llvm-11/lib -lclang
|
||||
#cgo darwin LDFLAGS: -L/usr/local/opt/llvm@11/lib -lclang -lffi
|
||||
#cgo freebsd LDFLAGS: -L/usr/local/llvm11/lib -lclang
|
||||
*/
|
||||
import "C"
|
||||
+12
-3
@@ -118,12 +118,12 @@ func (c *Config) NeedsStackObjects() bool {
|
||||
switch c.GC() {
|
||||
case "conservative", "extalloc":
|
||||
for _, tag := range c.BuildTags() {
|
||||
if tag == "baremetal" {
|
||||
return false
|
||||
if tag == "wasm" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
return false
|
||||
default:
|
||||
return false
|
||||
}
|
||||
@@ -329,6 +329,15 @@ func (c *Config) RelocationModel() string {
|
||||
return "static"
|
||||
}
|
||||
|
||||
// WasmAbi returns the WASM ABI which is specified in the target JSON file, and
|
||||
// the value is overridden by `-wasm-abi` flag if it is provided
|
||||
func (c *Config) WasmAbi() string {
|
||||
if c.Options.WasmAbi != "" {
|
||||
return c.Options.WasmAbi
|
||||
}
|
||||
return c.Target.WasmAbi
|
||||
}
|
||||
|
||||
type TestConfig struct {
|
||||
CompileTestBinary bool
|
||||
// TODO: Filter the test functions to run, include verbose flag, etc
|
||||
|
||||
+61
-111
@@ -8,6 +8,7 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
@@ -39,7 +40,7 @@ type TargetSpec struct {
|
||||
LDFlags []string `json:"ldflags"`
|
||||
LinkerScript string `json:"linkerscript"`
|
||||
ExtraFiles []string `json:"extra-files"`
|
||||
Emulator []string `json:"emulator"`
|
||||
Emulator []string `json:"emulator" override:"copy"` // inherited Emulator must not be append
|
||||
FlashCommand string `json:"flash-command"`
|
||||
GDB string `json:"gdb"`
|
||||
PortReset string `json:"flash-1200-bps-reset"`
|
||||
@@ -54,102 +55,49 @@ type TargetSpec struct {
|
||||
JLinkDevice string `json:"jlink-device"`
|
||||
CodeModel string `json:"code-model"`
|
||||
RelocationModel string `json:"relocation-model"`
|
||||
WasmAbi string `json:"wasm-abi"`
|
||||
}
|
||||
|
||||
// copyProperties copies all properties that are set in spec2 into itself.
|
||||
func (spec *TargetSpec) copyProperties(spec2 *TargetSpec) {
|
||||
// TODO: simplify this using reflection? Inherits and BuildTags are special
|
||||
// cases, but the rest can simply be copied if set.
|
||||
spec.Inherits = append(spec.Inherits, spec2.Inherits...)
|
||||
if spec2.Triple != "" {
|
||||
spec.Triple = spec2.Triple
|
||||
}
|
||||
if spec2.CPU != "" {
|
||||
spec.CPU = spec2.CPU
|
||||
}
|
||||
spec.Features = append(spec.Features, spec2.Features...)
|
||||
if spec2.GOOS != "" {
|
||||
spec.GOOS = spec2.GOOS
|
||||
}
|
||||
if spec2.GOARCH != "" {
|
||||
spec.GOARCH = spec2.GOARCH
|
||||
}
|
||||
spec.BuildTags = append(spec.BuildTags, spec2.BuildTags...)
|
||||
if spec2.GC != "" {
|
||||
spec.GC = spec2.GC
|
||||
}
|
||||
if spec2.Scheduler != "" {
|
||||
spec.Scheduler = spec2.Scheduler
|
||||
}
|
||||
if spec2.Compiler != "" {
|
||||
spec.Compiler = spec2.Compiler
|
||||
}
|
||||
if spec2.Linker != "" {
|
||||
spec.Linker = spec2.Linker
|
||||
}
|
||||
if spec2.RTLib != "" {
|
||||
spec.RTLib = spec2.RTLib
|
||||
}
|
||||
if spec2.Libc != "" {
|
||||
spec.Libc = spec2.Libc
|
||||
}
|
||||
if spec2.AutoStackSize != nil {
|
||||
spec.AutoStackSize = spec2.AutoStackSize
|
||||
}
|
||||
if spec2.DefaultStackSize != 0 {
|
||||
spec.DefaultStackSize = spec2.DefaultStackSize
|
||||
}
|
||||
spec.CFlags = append(spec.CFlags, spec2.CFlags...)
|
||||
spec.LDFlags = append(spec.LDFlags, spec2.LDFlags...)
|
||||
if spec2.LinkerScript != "" {
|
||||
spec.LinkerScript = spec2.LinkerScript
|
||||
}
|
||||
spec.ExtraFiles = append(spec.ExtraFiles, spec2.ExtraFiles...)
|
||||
if len(spec2.Emulator) != 0 {
|
||||
spec.Emulator = spec2.Emulator
|
||||
}
|
||||
if spec2.FlashCommand != "" {
|
||||
spec.FlashCommand = spec2.FlashCommand
|
||||
}
|
||||
if spec2.GDB != "" {
|
||||
spec.GDB = spec2.GDB
|
||||
}
|
||||
if spec2.PortReset != "" {
|
||||
spec.PortReset = spec2.PortReset
|
||||
}
|
||||
if spec2.FlashMethod != "" {
|
||||
spec.FlashMethod = spec2.FlashMethod
|
||||
}
|
||||
if spec2.FlashVolume != "" {
|
||||
spec.FlashVolume = spec2.FlashVolume
|
||||
}
|
||||
if spec2.FlashFilename != "" {
|
||||
spec.FlashFilename = spec2.FlashFilename
|
||||
}
|
||||
if spec2.UF2FamilyID != "" {
|
||||
spec.UF2FamilyID = spec2.UF2FamilyID
|
||||
}
|
||||
if spec2.BinaryFormat != "" {
|
||||
spec.BinaryFormat = spec2.BinaryFormat
|
||||
}
|
||||
if spec2.OpenOCDInterface != "" {
|
||||
spec.OpenOCDInterface = spec2.OpenOCDInterface
|
||||
}
|
||||
if spec2.OpenOCDTarget != "" {
|
||||
spec.OpenOCDTarget = spec2.OpenOCDTarget
|
||||
}
|
||||
if spec2.OpenOCDTransport != "" {
|
||||
spec.OpenOCDTransport = spec2.OpenOCDTransport
|
||||
}
|
||||
if spec2.JLinkDevice != "" {
|
||||
spec.JLinkDevice = spec2.JLinkDevice
|
||||
}
|
||||
if spec2.CodeModel != "" {
|
||||
spec.CodeModel = spec2.CodeModel
|
||||
}
|
||||
// overrideProperties overrides all properties that are set in child into itself using reflection.
|
||||
func (spec *TargetSpec) overrideProperties(child *TargetSpec) {
|
||||
specType := reflect.TypeOf(spec).Elem()
|
||||
specValue := reflect.ValueOf(spec).Elem()
|
||||
childValue := reflect.ValueOf(child).Elem()
|
||||
|
||||
if spec2.RelocationModel != "" {
|
||||
spec.RelocationModel = spec2.RelocationModel
|
||||
for i := 0; i < specType.NumField(); i++ {
|
||||
field := specType.Field(i)
|
||||
src := childValue.Field(i)
|
||||
dst := specValue.Field(i)
|
||||
|
||||
switch kind := field.Type.Kind(); kind {
|
||||
case reflect.String: // for strings, just copy the field of child to spec if not empty
|
||||
if src.Len() > 0 {
|
||||
dst.Set(src)
|
||||
}
|
||||
case reflect.Uint, reflect.Uint32, reflect.Uint64: // for Uint, copy if not zero
|
||||
if src.Uint() != 0 {
|
||||
dst.Set(src)
|
||||
}
|
||||
case reflect.Ptr: // for pointers, copy if not nil
|
||||
if !src.IsNil() {
|
||||
dst.Set(src)
|
||||
}
|
||||
case reflect.Slice: // for slices...
|
||||
if src.Len() > 0 { // ... if not empty ...
|
||||
switch tag := field.Tag.Get("override"); tag {
|
||||
case "copy":
|
||||
// copy the field of child to spec
|
||||
dst.Set(src)
|
||||
case "append", "":
|
||||
// or append the field of child to spec
|
||||
dst.Set(reflect.AppendSlice(src, dst))
|
||||
default:
|
||||
panic("override mode must be 'copy' or 'append' (default). I don't know how to '" + tag + "'.")
|
||||
}
|
||||
}
|
||||
default:
|
||||
panic("unknown field type : " + kind.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,11 +146,11 @@ func (spec *TargetSpec) resolveInherits() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newSpec.copyProperties(subtarget)
|
||||
newSpec.overrideProperties(subtarget)
|
||||
}
|
||||
|
||||
// When all properties are loaded, make sure they are properly inherited.
|
||||
newSpec.copyProperties(spec)
|
||||
newSpec.overrideProperties(spec)
|
||||
*spec = *newSpec
|
||||
|
||||
return nil
|
||||
@@ -268,6 +216,7 @@ func LoadTarget(target string) (*TargetSpec, error) {
|
||||
}
|
||||
goarch := map[string]string{ // map from LLVM arch to Go arch
|
||||
"i386": "386",
|
||||
"i686": "386",
|
||||
"x86_64": "amd64",
|
||||
"aarch64": "arm64",
|
||||
"armv7": "arm",
|
||||
@@ -283,39 +232,40 @@ func defaultTarget(goos, goarch, triple string) (*TargetSpec, error) {
|
||||
// No target spec available. Use the default one, useful on most systems
|
||||
// with a regular OS.
|
||||
spec := TargetSpec{
|
||||
Triple: triple,
|
||||
GOOS: goos,
|
||||
GOARCH: goarch,
|
||||
BuildTags: []string{goos, goarch},
|
||||
Compiler: "clang",
|
||||
Linker: "cc",
|
||||
CFlags: []string{"--target=" + triple},
|
||||
GDB: "gdb",
|
||||
PortReset: "false",
|
||||
FlashMethod: "native",
|
||||
Triple: triple,
|
||||
GOOS: goos,
|
||||
GOARCH: goarch,
|
||||
BuildTags: []string{goos, goarch},
|
||||
Compiler: "clang",
|
||||
Linker: "cc",
|
||||
CFlags: []string{"--target=" + triple},
|
||||
GDB: "gdb",
|
||||
PortReset: "false",
|
||||
}
|
||||
if goos == "darwin" {
|
||||
spec.LDFlags = append(spec.LDFlags, "-Wl,-dead_strip")
|
||||
} else {
|
||||
spec.LDFlags = append(spec.LDFlags, "-no-pie", "-Wl,--gc-sections") // WARNING: clang < 5.0 requires -nopie
|
||||
}
|
||||
if goarch != "wasm" {
|
||||
spec.ExtraFiles = append(spec.ExtraFiles, "src/runtime/gc_"+goarch+".S")
|
||||
}
|
||||
if goarch != runtime.GOARCH {
|
||||
// Some educated guesses as to how to invoke helper programs.
|
||||
spec.GDB = "gdb-multiarch"
|
||||
if goarch == "arm" && goos == "linux" {
|
||||
spec.CFlags = append(spec.CFlags, "--sysroot=/usr/arm-linux-gnueabihf")
|
||||
spec.Linker = "arm-linux-gnueabihf-gcc"
|
||||
spec.GDB = "arm-linux-gnueabihf-gdb"
|
||||
spec.Emulator = []string{"qemu-arm", "-L", "/usr/arm-linux-gnueabihf"}
|
||||
}
|
||||
if goarch == "arm64" && goos == "linux" {
|
||||
spec.CFlags = append(spec.CFlags, "--sysroot=/usr/aarch64-linux-gnu")
|
||||
spec.Linker = "aarch64-linux-gnu-gcc"
|
||||
spec.GDB = "aarch64-linux-gnu-gdb"
|
||||
spec.Emulator = []string{"qemu-aarch64", "-L", "/usr/aarch64-linux-gnu"}
|
||||
}
|
||||
if goarch == "386" {
|
||||
spec.CFlags = []string{"-m32"}
|
||||
spec.LDFlags = []string{"-m32"}
|
||||
if goarch == "386" && runtime.GOARCH == "amd64" {
|
||||
spec.CFlags = append(spec.CFlags, "-m32")
|
||||
spec.LDFlags = append(spec.LDFlags, "-m32")
|
||||
}
|
||||
}
|
||||
return &spec, nil
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package compileopts
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestLoadTarget(t *testing.T) {
|
||||
_, err := LoadTarget("arduino")
|
||||
@@ -17,3 +20,67 @@ func TestLoadTarget(t *testing.T) {
|
||||
t.Error("LoadTarget failed for wrong reason:", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOverrideProperties(t *testing.T) {
|
||||
baseAutoStackSize := true
|
||||
base := &TargetSpec{
|
||||
GOOS: "baseGoos",
|
||||
CPU: "baseCpu",
|
||||
Features: []string{"bf1", "bf2"},
|
||||
BuildTags: []string{"bt1", "bt2"},
|
||||
Emulator: []string{"be1", "be2"},
|
||||
DefaultStackSize: 42,
|
||||
AutoStackSize: &baseAutoStackSize,
|
||||
}
|
||||
childAutoStackSize := false
|
||||
child := &TargetSpec{
|
||||
GOOS: "",
|
||||
CPU: "chlidCpu",
|
||||
Features: []string{"cf1", "cf2"},
|
||||
Emulator: []string{"ce1", "ce2"},
|
||||
AutoStackSize: &childAutoStackSize,
|
||||
DefaultStackSize: 64,
|
||||
}
|
||||
|
||||
base.overrideProperties(child)
|
||||
|
||||
if base.GOOS != "baseGoos" {
|
||||
t.Errorf("Overriding failed : got %v", base.GOOS)
|
||||
}
|
||||
if base.CPU != "chlidCpu" {
|
||||
t.Errorf("Overriding failed : got %v", base.CPU)
|
||||
}
|
||||
if !reflect.DeepEqual(base.Features, []string{"cf1", "cf2", "bf1", "bf2"}) {
|
||||
t.Errorf("Overriding failed : got %v", base.Features)
|
||||
}
|
||||
if !reflect.DeepEqual(base.BuildTags, []string{"bt1", "bt2"}) {
|
||||
t.Errorf("Overriding failed : got %v", base.BuildTags)
|
||||
}
|
||||
if !reflect.DeepEqual(base.Emulator, []string{"ce1", "ce2"}) {
|
||||
t.Errorf("Overriding failed : got %v", base.Emulator)
|
||||
}
|
||||
if *base.AutoStackSize != false {
|
||||
t.Errorf("Overriding failed : got %v", base.AutoStackSize)
|
||||
}
|
||||
if base.DefaultStackSize != 64 {
|
||||
t.Errorf("Overriding failed : got %v", base.DefaultStackSize)
|
||||
}
|
||||
|
||||
baseAutoStackSize = true
|
||||
base = &TargetSpec{
|
||||
AutoStackSize: &baseAutoStackSize,
|
||||
DefaultStackSize: 42,
|
||||
}
|
||||
child = &TargetSpec{
|
||||
AutoStackSize: nil,
|
||||
DefaultStackSize: 0,
|
||||
}
|
||||
base.overrideProperties(child)
|
||||
if *base.AutoStackSize != true {
|
||||
t.Errorf("Overriding failed : got %v", base.AutoStackSize)
|
||||
}
|
||||
if base.DefaultStackSize != 42 {
|
||||
t.Errorf("Overriding failed : got %v", base.DefaultStackSize)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+20
-8
@@ -1336,12 +1336,14 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error)
|
||||
return b.createMemoryCopyCall(fn, instr.Args)
|
||||
case name == "runtime.memzero":
|
||||
return b.createMemoryZeroCall(instr.Args)
|
||||
case name == "device.Asm" || name == "device/arm.Asm" || name == "device/avr.Asm" || name == "device/riscv.Asm":
|
||||
case name == "device.Asm" || name == "device/arm.Asm" || name == "device/arm64.Asm" || name == "device/avr.Asm" || name == "device/riscv.Asm":
|
||||
return b.createInlineAsm(instr.Args)
|
||||
case name == "device.AsmFull" || name == "device/arm.AsmFull" || name == "device/avr.AsmFull" || name == "device/riscv.AsmFull":
|
||||
case name == "device.AsmFull" || name == "device/arm.AsmFull" || name == "device/arm64.AsmFull" || name == "device/avr.AsmFull" || name == "device/riscv.AsmFull":
|
||||
return b.createInlineAsmFull(instr)
|
||||
case strings.HasPrefix(name, "device/arm.SVCall"):
|
||||
return b.emitSVCall(instr.Args)
|
||||
case strings.HasPrefix(name, "device/arm64.SVCall"):
|
||||
return b.emitSV64Call(instr.Args)
|
||||
case strings.HasPrefix(name, "(device/riscv.CSR)."):
|
||||
return b.emitCSROperation(instr)
|
||||
case strings.HasPrefix(name, "syscall.Syscall"):
|
||||
@@ -2044,17 +2046,17 @@ func (b *builder) createBinOp(op token.Token, typ, ytyp types.Type, x, y llvm.Va
|
||||
case token.QUO: // /
|
||||
return b.CreateFDiv(x, y, ""), nil
|
||||
case token.EQL: // ==
|
||||
return b.CreateFCmp(llvm.FloatUEQ, x, y, ""), nil
|
||||
return b.CreateFCmp(llvm.FloatOEQ, x, y, ""), nil
|
||||
case token.NEQ: // !=
|
||||
return b.CreateFCmp(llvm.FloatUNE, x, y, ""), nil
|
||||
case token.LSS: // <
|
||||
return b.CreateFCmp(llvm.FloatULT, x, y, ""), nil
|
||||
return b.CreateFCmp(llvm.FloatOLT, x, y, ""), nil
|
||||
case token.LEQ: // <=
|
||||
return b.CreateFCmp(llvm.FloatULE, x, y, ""), nil
|
||||
return b.CreateFCmp(llvm.FloatOLE, x, y, ""), nil
|
||||
case token.GTR: // >
|
||||
return b.CreateFCmp(llvm.FloatUGT, x, y, ""), nil
|
||||
return b.CreateFCmp(llvm.FloatOGT, x, y, ""), nil
|
||||
case token.GEQ: // >=
|
||||
return b.CreateFCmp(llvm.FloatUGE, x, y, ""), nil
|
||||
return b.CreateFCmp(llvm.FloatOGE, x, y, ""), nil
|
||||
default:
|
||||
panic("binop on float: " + op.String())
|
||||
}
|
||||
@@ -2578,7 +2580,17 @@ func (b *builder) createUnOp(unop *ssa.UnOp) (llvm.Value, error) {
|
||||
if typ.Info()&types.IsInteger != 0 {
|
||||
return b.CreateSub(llvm.ConstInt(x.Type(), 0, false), x, ""), nil
|
||||
} else if typ.Info()&types.IsFloat != 0 {
|
||||
return b.CreateFSub(llvm.ConstFloat(x.Type(), 0.0), x, ""), nil
|
||||
return b.CreateFNeg(x, ""), nil
|
||||
} else if typ.Info()&types.IsComplex != 0 {
|
||||
// Negate both components of the complex number.
|
||||
r := b.CreateExtractValue(x, 0, "r")
|
||||
i := b.CreateExtractValue(x, 1, "i")
|
||||
r = b.CreateFNeg(r, "")
|
||||
i = b.CreateFNeg(i, "")
|
||||
cplx := llvm.Undef(x.Type())
|
||||
cplx = b.CreateInsertValue(cplx, r, 0, "")
|
||||
cplx = b.CreateInsertValue(cplx, i, 1, "")
|
||||
return cplx, nil
|
||||
} else {
|
||||
return llvm.Value{}, b.makeError(unop.Pos(), "todo: unknown basic type for negate: "+typ.String())
|
||||
}
|
||||
|
||||
@@ -163,6 +163,44 @@ func (b *builder) emitSVCall(args []ssa.Value) (llvm.Value, error) {
|
||||
return b.CreateCall(target, llvmArgs, ""), nil
|
||||
}
|
||||
|
||||
// This is a compiler builtin which emits an inline SVCall instruction. It can
|
||||
// be one of:
|
||||
//
|
||||
// func SVCall0(num uintptr) uintptr
|
||||
// func SVCall1(num uintptr, a1 interface{}) uintptr
|
||||
// func SVCall2(num uintptr, a1, a2 interface{}) uintptr
|
||||
// func SVCall3(num uintptr, a1, a2, a3 interface{}) uintptr
|
||||
// func SVCall4(num uintptr, a1, a2, a3, a4 interface{}) uintptr
|
||||
//
|
||||
// The num parameter must be a constant. All other parameters may be any scalar
|
||||
// value supported by LLVM inline assembly.
|
||||
// Same as emitSVCall but for AArch64
|
||||
func (b *builder) emitSV64Call(args []ssa.Value) (llvm.Value, error) {
|
||||
num, _ := constant.Uint64Val(args[0].(*ssa.Const).Value)
|
||||
llvmArgs := []llvm.Value{}
|
||||
argTypes := []llvm.Type{}
|
||||
asm := "svc #" + strconv.FormatUint(num, 10)
|
||||
constraints := "={x0}"
|
||||
for i, arg := range args[1:] {
|
||||
arg = arg.(*ssa.MakeInterface).X
|
||||
if i == 0 {
|
||||
constraints += ",0"
|
||||
} else {
|
||||
constraints += ",{x" + strconv.Itoa(i) + "}"
|
||||
}
|
||||
llvmValue := b.getValue(arg)
|
||||
llvmArgs = append(llvmArgs, llvmValue)
|
||||
argTypes = append(argTypes, llvmValue.Type())
|
||||
}
|
||||
// Implement the ARM64 calling convention by marking x1-x7 as
|
||||
// clobbered. x0 is used as an output register so doesn't have to be
|
||||
// marked as clobbered.
|
||||
constraints += ",~{x1},~{x2},~{x3},~{x4},~{x5},~{x6},~{x7}"
|
||||
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
|
||||
target := llvm.InlineAsm(fnType, asm, constraints, true, false, 0)
|
||||
return b.CreateCall(target, llvmArgs, ""), nil
|
||||
}
|
||||
|
||||
// This is a compiler builtin which emits CSR instructions. It can be one of:
|
||||
//
|
||||
// func (csr CSR) Get() uintptr
|
||||
|
||||
@@ -4,11 +4,11 @@ go 1.11
|
||||
|
||||
require (
|
||||
github.com/blakesmith/ar v0.0.0-20150311145944-8bd4349a67f2
|
||||
github.com/chromedp/cdproto v0.0.0-20200116234248-4da64dd111ac
|
||||
github.com/chromedp/chromedp v0.5.3
|
||||
github.com/chromedp/cdproto v0.0.0-20200709115526-d1f6fc58448b
|
||||
github.com/chromedp/chromedp v0.5.4-0.20200303084119-2bb39134ab9e
|
||||
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf
|
||||
github.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892
|
||||
go.bug.st/serial v1.0.0
|
||||
golang.org/x/tools v0.0.0-20200216192241-b320d3a0f5a2
|
||||
tinygo.org/x/go-llvm v0.0.0-20200503225853-345b2947b59d
|
||||
tinygo.org/x/go-llvm v0.0.0-20201104183921-570e7a6841d9
|
||||
)
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
github.com/blakesmith/ar v0.0.0-20150311145944-8bd4349a67f2 h1:oMCHnXa6CCCafdPDbMh/lWRhRByN0VFLvv+g+ayx1SI=
|
||||
github.com/blakesmith/ar v0.0.0-20150311145944-8bd4349a67f2/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI=
|
||||
github.com/chromedp/cdproto v0.0.0-20200116234248-4da64dd111ac h1:T7V5BXqnYd55Hj/g5uhDYumg9Fp3rMTS6bykYtTIFX4=
|
||||
github.com/chromedp/cdproto v0.0.0-20200116234248-4da64dd111ac/go.mod h1:PfAWWKJqjlGFYJEidUM6aVIWPr0EpobeyVWEEmplX7g=
|
||||
github.com/chromedp/chromedp v0.5.3 h1:F9LafxmYpsQhWQBdCs+6Sret1zzeeFyHS5LkRF//Ffg=
|
||||
github.com/chromedp/chromedp v0.5.3/go.mod h1:YLdPtndaHQ4rCpSpBG+IPpy9JvX0VD+7aaLxYgYj28w=
|
||||
github.com/chromedp/cdproto v0.0.0-20200709115526-d1f6fc58448b h1:LF+GRwyzxrO3MUzPvejv+yBup0lNG+/QdIRrkxOPseA=
|
||||
github.com/chromedp/cdproto v0.0.0-20200709115526-d1f6fc58448b/go.mod h1:E6LPWRdIJc11h/di5p0rwvRmUYbhGpBEH7ZbPfzDIOE=
|
||||
github.com/chromedp/chromedp v0.5.4-0.20200303084119-2bb39134ab9e h1:Hv0JVyHhbIXb9NiYQe4NsrfgrSofAp0q2FnhhJOXgi8=
|
||||
github.com/chromedp/chromedp v0.5.4-0.20200303084119-2bb39134ab9e/go.mod h1:vmQMRHFZrY3T+Jv51T0n87OK/i6bK+5P9a+Fg5jPwgQ=
|
||||
github.com/creack/goselect v0.1.1 h1:tiSSgKE1eJtxs1h/VgGQWuXUP0YS4CDIFMp6vaI1ls0=
|
||||
github.com/creack/goselect v0.1.1/go.mod h1:a/NhLweNvqIYMuxcMOuWY516Cimucms3DglDzQP3hKY=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@@ -11,14 +12,15 @@ github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah
|
||||
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
|
||||
github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8=
|
||||
github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
|
||||
github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo=
|
||||
github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
|
||||
github.com/gobwas/ws v1.0.3 h1:ZOigqf7iBxkA4jdQ3am7ATzdlOFp9YzA6NmuvEEZc9g=
|
||||
github.com/gobwas/ws v1.0.3/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
|
||||
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf h1:7+FW5aGwISbqUtkfmIpZJGRgNFg2ioYPvFaUxdqpDsg=
|
||||
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf/go.mod h1:RpwtwJQFrIEPstU94h88MWPXP2ektJZ8cZ0YntAmXiE=
|
||||
github.com/knq/sysutil v0.0.0-20191005231841-15668db23d08 h1:V0an7KRw92wmJysvFvtqtKMAPmvS5O0jtB0nYo6t+gs=
|
||||
github.com/knq/sysutil v0.0.0-20191005231841-15668db23d08/go.mod h1:dFWs1zEqDjFtnBXsd1vPOZaLsESovai349994nHx3e0=
|
||||
github.com/mailru/easyjson v0.7.0 h1:aizVhC/NAAcKWb+5QsU1iNOZb4Yws5UO2I+aIprQITM=
|
||||
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
|
||||
github.com/mailru/easyjson v0.7.1 h1:mdxE1MF9o53iCb2Ghj1VfWvh7ZOwHpnVG/xwXrV90U8=
|
||||
github.com/mailru/easyjson v0.7.1/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
|
||||
github.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892 h1:6J+qramlHVLmiBOgRiBOnQkno8uprqG6YFFQTt6uYIw=
|
||||
github.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892/go.mod h1:Pb6XcsXyropB9LNHhnqaknG/vEwYztLkQzVCHv8sQ3M=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
@@ -46,5 +48,5 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbO
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
tinygo.org/x/go-llvm v0.0.0-20200503225853-345b2947b59d h1:hcX7vpB067GWM/EH4sGGOti0PMgIx+0bbZwUXctOIvE=
|
||||
tinygo.org/x/go-llvm v0.0.0-20200503225853-345b2947b59d/go.mod h1:fv1F0BSNpxMfCL0zF3M4OPFbgYHnhtB6ST0HvUtu/LE=
|
||||
tinygo.org/x/go-llvm v0.0.0-20201104183921-570e7a6841d9 h1:l2kTQOhqEoeDTK3ckUnwReOQwMPUmURMIdjJbeAuDT4=
|
||||
tinygo.org/x/go-llvm v0.0.0-20201104183921-570e7a6841d9/go.mod h1:fv1F0BSNpxMfCL0zF3M4OPFbgYHnhtB6ST0HvUtu/LE=
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ import (
|
||||
|
||||
// Version of TinyGo.
|
||||
// Update this value before release of new version of software.
|
||||
const Version = "0.15.0"
|
||||
const Version = "0.16.0"
|
||||
|
||||
// GetGorootVersion returns the major and minor version for a given GOROOT path.
|
||||
// If the goroot cannot be determined, (0, 0) is returned.
|
||||
|
||||
+15
-2
@@ -3,6 +3,7 @@ package interp
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@@ -66,6 +67,8 @@ func runTest(t *testing.T, pathPrefix string) {
|
||||
}
|
||||
}
|
||||
|
||||
var alignRegexp = regexp.MustCompile(", align [0-9]+$")
|
||||
|
||||
// fuzzyEqualIR returns true if the two LLVM IR strings passed in are roughly
|
||||
// equal. That means, only relevant lines are compared (excluding comments
|
||||
// etc.).
|
||||
@@ -75,8 +78,18 @@ func fuzzyEqualIR(s1, s2 string) bool {
|
||||
if len(lines1) != len(lines2) {
|
||||
return false
|
||||
}
|
||||
for i, line := range lines1 {
|
||||
if line != lines2[i] {
|
||||
for i, line1 := range lines1 {
|
||||
line2 := lines2[i]
|
||||
match1 := alignRegexp.MatchString(line1)
|
||||
match2 := alignRegexp.MatchString(line2)
|
||||
if match1 != match2 {
|
||||
// Only one of the lines has the align keyword. Remove it.
|
||||
// This is a change to make the test work in both LLVM 10 and LLVM
|
||||
// 11 (LLVM 11 appears to automatically add alignment everywhere).
|
||||
line1 = alignRegexp.ReplaceAllString(line1, "")
|
||||
line2 = alignRegexp.ReplaceAllString(line2, "")
|
||||
}
|
||||
if line1 != line2 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -189,7 +189,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" || tag == "nintendoswitch" {
|
||||
if tag == "baremetal" || tag == "darwin" || tag == "nintendoswitch" || tag == "wasi" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
+36
-7
@@ -51,8 +51,7 @@ type PackageJSON struct {
|
||||
CFiles []string
|
||||
|
||||
// Dependency information
|
||||
Imports []string
|
||||
ImportMap map[string]string
|
||||
Imports []string
|
||||
|
||||
// Error information
|
||||
Error *struct {
|
||||
@@ -169,6 +168,41 @@ func Load(config *compileopts.Config, inputPkgs []string, clangHeaders string, t
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
if config.TestConfig.CompileTestBinary {
|
||||
// When creating a test binary, `go list` will list two or three
|
||||
// packages used for testing the package. The first is the original
|
||||
// package as if it were built normally, the second is the same
|
||||
// package but with the *_test.go files included. A possible third
|
||||
// may be included for _test packages (such as math_test), used to
|
||||
// test the external API with no access to internal functions.
|
||||
// All packages that are necessary for testing (including the to be
|
||||
// tested package with *_test.go files, but excluding the original
|
||||
// unmodified package) have a suffix added to the import path, for
|
||||
// example the math package has import path "math [math.test]" and
|
||||
// test dependencies such as fmt will have an import path of the
|
||||
// form "fmt [math.test]".
|
||||
// The code below removes this suffix, and if this results in a
|
||||
// duplicate (which happens with the to-be-tested package without
|
||||
// *.test.go files) the previous package is removed from the list of
|
||||
// packages included in this build.
|
||||
// This is necessary because the change in import paths results in
|
||||
// breakage to //go:linkname. Additionally, the duplicated package
|
||||
// slows down the build and so is best removed.
|
||||
if pkg.ForTest != "" && strings.HasSuffix(pkg.ImportPath, " ["+pkg.ForTest+".test]") {
|
||||
newImportPath := pkg.ImportPath[:len(pkg.ImportPath)-len(" ["+pkg.ForTest+".test]")]
|
||||
if _, ok := p.Packages[newImportPath]; ok {
|
||||
// Delete the previous package (that this package overrides).
|
||||
delete(p.Packages, newImportPath)
|
||||
for i, pkg := range p.sorted {
|
||||
if pkg.ImportPath == newImportPath {
|
||||
p.sorted = append(p.sorted[:i], p.sorted[i+1:]...) // remove element from slice
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
pkg.ImportPath = newImportPath
|
||||
}
|
||||
}
|
||||
p.sorted = append(p.sorted, pkg)
|
||||
p.Packages[pkg.ImportPath] = pkg
|
||||
}
|
||||
@@ -367,11 +401,6 @@ func (p *Package) Import(to string) (*types.Package, error) {
|
||||
if to == "unsafe" {
|
||||
return types.Unsafe, nil
|
||||
}
|
||||
if replace, ok := p.ImportMap[to]; ok {
|
||||
// This import path should be replaced by another import path, according
|
||||
// to `go list`.
|
||||
to = replace
|
||||
}
|
||||
if imported, ok := p.program.Packages[to]; ok {
|
||||
return imported.Pkg, nil
|
||||
} else {
|
||||
|
||||
@@ -74,7 +74,12 @@ func copyFile(src, dst string) error {
|
||||
}
|
||||
defer source.Close()
|
||||
|
||||
destination, err := os.Create(dst)
|
||||
st, err := source.Stat()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
destination, err := os.OpenFile(dst, os.O_RDWR|os.O_CREATE|os.O_TRUNC, st.Mode())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -120,30 +125,71 @@ func Build(pkgName, outpath string, options *compileopts.Options) error {
|
||||
}
|
||||
|
||||
// Test runs the tests in the given package.
|
||||
func Test(pkgName string, options *compileopts.Options) error {
|
||||
func Test(pkgName string, options *compileopts.Options, testCompileOnly bool, outpath string) error {
|
||||
options.TestConfig.CompileTestBinary = true
|
||||
config, err := builder.NewConfig(options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return builder.Build(pkgName, ".elf", config, func(result builder.BuildResult) error {
|
||||
cmd := exec.Command(result.Binary)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
cmd.Dir = result.MainDir
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
// Propagate the exit code
|
||||
if err, ok := err.(*exec.ExitError); ok {
|
||||
if status, ok := err.Sys().(syscall.WaitStatus); ok {
|
||||
os.Exit(status.ExitStatus())
|
||||
}
|
||||
os.Exit(1)
|
||||
return builder.Build(pkgName, outpath, config, func(result builder.BuildResult) error {
|
||||
if testCompileOnly || outpath != "" {
|
||||
// Write test binary to the specified file name.
|
||||
if outpath == "" {
|
||||
// No -o path was given, so create one now.
|
||||
// This matches the behavior of go test.
|
||||
outpath = filepath.Base(result.MainDir) + ".test"
|
||||
}
|
||||
copyFile(result.Binary, outpath)
|
||||
}
|
||||
if testCompileOnly {
|
||||
// Do not run the test.
|
||||
return nil
|
||||
}
|
||||
if len(config.Target.Emulator) == 0 {
|
||||
// Run directly.
|
||||
cmd := exec.Command(result.Binary)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
cmd.Dir = result.MainDir
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
// Propagate the exit code
|
||||
if err, ok := err.(*exec.ExitError); ok {
|
||||
if status, ok := err.Sys().(syscall.WaitStatus); ok {
|
||||
os.Exit(status.ExitStatus())
|
||||
}
|
||||
os.Exit(1)
|
||||
}
|
||||
return &commandError{"failed to run compiled binary", result.Binary, err}
|
||||
}
|
||||
return nil
|
||||
} else {
|
||||
// Run in an emulator.
|
||||
args := append(config.Target.Emulator[1:], result.Binary)
|
||||
cmd := exec.Command(config.Target.Emulator[0], args...)
|
||||
buf := &bytes.Buffer{}
|
||||
w := io.MultiWriter(os.Stdout, buf)
|
||||
cmd.Stdout = w
|
||||
cmd.Stderr = os.Stderr
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
if err, ok := err.(*exec.ExitError); !ok || !err.Exited() {
|
||||
// Workaround for QEMU which always exits with an error.
|
||||
return &commandError{"failed to run emulator with", result.Binary, err}
|
||||
}
|
||||
}
|
||||
testOutput := string(buf.Bytes())
|
||||
if testOutput == "PASS\n" || strings.HasSuffix(testOutput, "\nPASS\n") {
|
||||
// Test passed.
|
||||
return nil
|
||||
} else {
|
||||
// Test failed, either by ending with the word "FAIL" or with a
|
||||
// panic of some sort.
|
||||
os.Exit(1)
|
||||
return nil // unreachable
|
||||
}
|
||||
return &commandError{"failed to run compiled binary", result.Binary, err}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@@ -305,13 +351,17 @@ func FlashGDB(pkgName string, ocdOutput bool, options *compileopts.Options) erro
|
||||
// Assume QEMU as an emulator.
|
||||
if config.Target.Emulator[0] == "mgba" {
|
||||
gdbInterface = "mgba"
|
||||
} else {
|
||||
} else if strings.HasPrefix(config.Target.Emulator[0], "qemu-system-") {
|
||||
gdbInterface = "qemu"
|
||||
} else {
|
||||
gdbInterface = "qemu-user"
|
||||
}
|
||||
} else if openocdInterface != "" && config.Target.OpenOCDTarget != "" {
|
||||
gdbInterface = "openocd"
|
||||
} else if config.Target.JLinkDevice != "" {
|
||||
gdbInterface = "jlink"
|
||||
} else {
|
||||
gdbInterface = "native"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -363,6 +413,14 @@ func FlashGDB(pkgName string, ocdOutput bool, options *compileopts.Options) erro
|
||||
daemon = exec.Command(config.Target.Emulator[0], args...)
|
||||
daemon.Stdout = os.Stdout
|
||||
daemon.Stderr = os.Stderr
|
||||
case "qemu-user":
|
||||
gdbCommands = append(gdbCommands, "target remote :1234")
|
||||
|
||||
// Run in an emulator.
|
||||
args := append(config.Target.Emulator[1:], "-g", "1234", result.Binary)
|
||||
daemon = exec.Command(config.Target.Emulator[0], args...)
|
||||
daemon.Stdout = os.Stdout
|
||||
daemon.Stderr = os.Stderr
|
||||
case "mgba":
|
||||
gdbCommands = append(gdbCommands, "target remote :2345")
|
||||
|
||||
@@ -753,7 +811,6 @@ func main() {
|
||||
}
|
||||
command := os.Args[1]
|
||||
|
||||
outpath := flag.String("o", "", "output filename")
|
||||
opt := flag.String("opt", "z", "optimization level: 0, 1, 2, s, z")
|
||||
gc := flag.String("gc", "", "garbage collector to use (none, leaking, extalloc, conservative)")
|
||||
panicStrategy := flag.String("panic", "print", "panic strategy (print, trap)")
|
||||
@@ -771,14 +828,22 @@ func main() {
|
||||
programmer := flag.String("programmer", "", "which hardware programmer to use")
|
||||
cFlags := flag.String("cflags", "", "additional cflags for compiler")
|
||||
ldFlags := flag.String("ldflags", "", "additional ldflags for linker")
|
||||
wasmAbi := flag.String("wasm-abi", "js", "WebAssembly ABI conventions: js (no i64 params) or generic")
|
||||
wasmAbi := flag.String("wasm-abi", "", "WebAssembly ABI conventions: js (no i64 params) or generic")
|
||||
heapSize := flag.String("heap-size", "1M", "default heap size in bytes (only supported by WebAssembly)")
|
||||
|
||||
var flagJSON, flagDeps *bool
|
||||
if command == "list" {
|
||||
if command == "help" || command == "list" {
|
||||
flagJSON = flag.Bool("json", false, "print data in JSON format")
|
||||
flagDeps = flag.Bool("deps", false, "")
|
||||
}
|
||||
var outpath string
|
||||
if command == "help" || command == "build" || command == "build-library" || command == "test" {
|
||||
flag.StringVar(&outpath, "o", "", "output filename")
|
||||
}
|
||||
var testCompileOnlyFlag *bool
|
||||
if command == "help" || command == "test" {
|
||||
testCompileOnlyFlag = flag.Bool("c", false, "compile the test binary but do not run it")
|
||||
}
|
||||
|
||||
// Early command processing, before commands are interpreted by the Go flag
|
||||
// library.
|
||||
@@ -836,7 +901,7 @@ func main() {
|
||||
|
||||
switch command {
|
||||
case "build":
|
||||
if *outpath == "" {
|
||||
if outpath == "" {
|
||||
fmt.Fprintln(os.Stderr, "No output filename supplied (-o).")
|
||||
usage()
|
||||
os.Exit(1)
|
||||
@@ -849,15 +914,15 @@ func main() {
|
||||
usage()
|
||||
os.Exit(1)
|
||||
}
|
||||
if options.Target == "" && filepath.Ext(*outpath) == ".wasm" {
|
||||
if options.Target == "" && filepath.Ext(outpath) == ".wasm" {
|
||||
options.Target = "wasm"
|
||||
}
|
||||
|
||||
err := Build(pkgName, *outpath, options)
|
||||
err := Build(pkgName, outpath, options)
|
||||
handleCompilerError(err)
|
||||
case "build-library":
|
||||
// Note: this command is only meant to be used while making a release!
|
||||
if *outpath == "" {
|
||||
if outpath == "" {
|
||||
fmt.Fprintln(os.Stderr, "No output filename supplied (-o).")
|
||||
usage()
|
||||
os.Exit(1)
|
||||
@@ -882,13 +947,8 @@ func main() {
|
||||
}
|
||||
path, err := lib.Load(*target)
|
||||
handleCompilerError(err)
|
||||
copyFile(path, *outpath)
|
||||
copyFile(path, outpath)
|
||||
case "flash", "gdb":
|
||||
if *outpath != "" {
|
||||
fmt.Fprintln(os.Stderr, "Output cannot be specified with the flash command.")
|
||||
usage()
|
||||
os.Exit(1)
|
||||
}
|
||||
pkgName := filepath.ToSlash(flag.Arg(0))
|
||||
if command == "flash" {
|
||||
err := Flash(pkgName, *port, options)
|
||||
@@ -920,7 +980,7 @@ func main() {
|
||||
usage()
|
||||
os.Exit(1)
|
||||
}
|
||||
err := Test(pkgName, options)
|
||||
err := Test(pkgName, options, *testCompileOnlyFlag, outpath)
|
||||
handleCompilerError(err)
|
||||
case "targets":
|
||||
dir := filepath.Join(goenv.Get("TINYGOROOT"), "targets")
|
||||
|
||||
+13
-5
@@ -78,6 +78,9 @@ func TestCompiler(t *testing.T) {
|
||||
}
|
||||
|
||||
if runtime.GOOS == "linux" {
|
||||
t.Run("X86Linux", func(t *testing.T) {
|
||||
runPlatTests("i386--linux-gnu", matches, t)
|
||||
})
|
||||
t.Run("ARMLinux", func(t *testing.T) {
|
||||
runPlatTests("arm--linux-gnueabihf", matches, t)
|
||||
})
|
||||
@@ -98,6 +101,10 @@ func TestCompiler(t *testing.T) {
|
||||
runPlatTests("wasm", matches, t)
|
||||
})
|
||||
}
|
||||
|
||||
t.Run("WASI", func(t *testing.T) {
|
||||
runPlatTests("wasi", matches, t)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,7 +116,6 @@ func runPlatTests(target string, matches []string, t *testing.T) {
|
||||
|
||||
t.Run(filepath.Base(path), func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
runTest(path, target, t)
|
||||
})
|
||||
}
|
||||
@@ -159,8 +165,9 @@ func runTest(path, target string, t *testing.T) {
|
||||
VerifyIR: true,
|
||||
Debug: true,
|
||||
PrintSizes: "",
|
||||
WasmAbi: "js",
|
||||
WasmAbi: "",
|
||||
}
|
||||
|
||||
binary := filepath.Join(tmpdir, "test")
|
||||
err = runBuild("./"+path, binary, config)
|
||||
if err != nil {
|
||||
@@ -181,10 +188,11 @@ func runTest(path, target string, t *testing.T) {
|
||||
t.Fatal("failed to load target spec:", err)
|
||||
}
|
||||
if len(spec.Emulator) == 0 {
|
||||
t.Fatal("no emulator available for target:", target)
|
||||
cmd = exec.Command(binary)
|
||||
} else {
|
||||
args := append(spec.Emulator[1:], binary)
|
||||
cmd = exec.Command(spec.Emulator[0], args...)
|
||||
}
|
||||
args := append(spec.Emulator[1:], binary)
|
||||
cmd = exec.Command(spec.Emulator[0], args...)
|
||||
}
|
||||
stdout := &bytes.Buffer{}
|
||||
cmd.Stdout = stdout
|
||||
|
||||
@@ -76,32 +76,8 @@ const (
|
||||
SCS_BASE = 0xE000E000
|
||||
SYST_BASE = SCS_BASE + 0x0010
|
||||
NVIC_BASE = SCS_BASE + 0x0100
|
||||
SCB_BASE = SCS_BASE + 0x0D00
|
||||
)
|
||||
|
||||
const (
|
||||
SCB_AIRCR_VECTKEY_Pos = 16
|
||||
SCB_AIRCR_SYSRESETREQ_Pos = 2
|
||||
SCB_AIRCR_SYSRESETREQ_Msk = 1 << SCB_AIRCR_SYSRESETREQ_Pos
|
||||
)
|
||||
|
||||
// System Control Block (SCB)
|
||||
//
|
||||
// SCB_Type provides the definitions for the System Control Block Registers.
|
||||
type SCB_Type struct {
|
||||
CPUID volatile.Register32 // CPUID Base Register
|
||||
ICSR volatile.Register32 // Interrupt Control and State Register
|
||||
VTOR volatile.Register32 // Vector Table Offset Register
|
||||
AIRCR volatile.Register32 // Application Interrupt and Reset Control Register
|
||||
SCR volatile.Register32 // System Control Register
|
||||
CCR volatile.Register32 // Configuration Control Register
|
||||
_ volatile.Register32 // RESERVED1;
|
||||
SHP [2]volatile.Register32 // System Handlers Priority Registers. [0] is RESERVED
|
||||
SHCSR volatile.Register32 // System Handler Control and State Register
|
||||
}
|
||||
|
||||
var SCB = (*SCB_Type)(unsafe.Pointer(uintptr(SCB_BASE)))
|
||||
|
||||
// Nested Vectored Interrupt Controller (NVIC).
|
||||
//
|
||||
// Source:
|
||||
@@ -213,17 +189,6 @@ func EnableInterrupts(mask uintptr) {
|
||||
})
|
||||
}
|
||||
|
||||
// SystemReset performs a hard system reset.
|
||||
func SystemReset() {
|
||||
// SCB->AIRCR = ((0x5FA << SCB_AIRCR_VECTKEY_Pos) |
|
||||
// SCB_AIRCR_SYSRESETREQ_Msk);
|
||||
SCB.AIRCR.Set((0x5FA << SCB_AIRCR_VECTKEY_Pos) | SCB_AIRCR_SYSRESETREQ_Msk)
|
||||
|
||||
for {
|
||||
Asm("wfi")
|
||||
}
|
||||
}
|
||||
|
||||
// Set up the system timer to generate periodic tick events.
|
||||
// This will cause SysTick_Handler to fire once per tick.
|
||||
// The cyclecount parameter is a counter value which can range from 0 to
|
||||
|
||||
@@ -0,0 +1,431 @@
|
||||
// Hand created file. DO NOT DELETE.
|
||||
// Cortex-M System Control Block-related definitions.
|
||||
|
||||
// +build cortexm
|
||||
|
||||
package arm
|
||||
|
||||
import (
|
||||
"runtime/volatile"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const SCB_BASE = SCS_BASE + 0x0D00
|
||||
|
||||
// System Control Block (SCB)
|
||||
//
|
||||
// SCB_Type provides the definitions for the System Control Block Registers.
|
||||
type SCB_Type struct {
|
||||
CPUID volatile.Register32 // 0xD00: CPUID Base Register
|
||||
ICSR volatile.Register32 // 0xD04: Interrupt Control and State Register
|
||||
VTOR volatile.Register32 // 0xD08: Vector Table Offset Register
|
||||
AIRCR volatile.Register32 // 0xD0C: Application Interrupt and Reset Control Register
|
||||
SCR volatile.Register32 // 0xD10: System Control Register
|
||||
CCR volatile.Register32 // 0xD14: Configuration and Control Register
|
||||
SHPR1 volatile.Register32 // 0xD18: System Handler Priority Register 1 (Cortex-M3/M33/M4/M7 only)
|
||||
SHPR2 volatile.Register32 // 0xD1C: System Handler Priority Register 2
|
||||
SHPR3 volatile.Register32 // 0xD20: System Handler Priority Register 3
|
||||
// the following are only applicable for Cortex-M3/M33/M4/M7
|
||||
SHCSR volatile.Register32 // 0xD24: System Handler Control and State Register
|
||||
CFSR volatile.Register32 // 0xD28: Configurable Fault Status Register
|
||||
HFSR volatile.Register32 // 0xD2C: HardFault Status Register
|
||||
DFSR volatile.Register32 // 0xD30: Debug Fault Status Register
|
||||
MMFAR volatile.Register32 // 0xD34: MemManage Fault Address Register
|
||||
BFAR volatile.Register32 // 0xD38: BusFault Address Register
|
||||
}
|
||||
|
||||
var SCB = (*SCB_Type)(unsafe.Pointer(uintptr(SCB_BASE)))
|
||||
|
||||
// SystemReset performs a hard system reset.
|
||||
func SystemReset() {
|
||||
SCB.AIRCR.Set((0x5FA << SCB_AIRCR_VECTKEY_Pos) | SCB_AIRCR_SYSRESETREQ_Msk)
|
||||
for {
|
||||
Asm("wfi")
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
// CPUID: CPUID Base Register
|
||||
SCB_CPUID_REVISION_Pos = 0x0 // Position of REVISION field.
|
||||
SCB_CPUID_REVISION_Msk = 0xf // Bit mask of REVISION field.
|
||||
SCB_CPUID_PARTNO_Pos = 0x4 // Position of PARTNO field.
|
||||
SCB_CPUID_PARTNO_Msk = 0xfff0 // Bit mask of PARTNO field.
|
||||
SCB_CPUID_ARCHITECTURE_Pos = 0x10 // Position of ARCHITECTURE field.
|
||||
SCB_CPUID_ARCHITECTURE_Msk = 0xf0000 // Bit mask of ARCHITECTURE field.
|
||||
SCB_CPUID_VARIANT_Pos = 0x14 // Position of VARIANT field.
|
||||
SCB_CPUID_VARIANT_Msk = 0xf00000 // Bit mask of VARIANT field.
|
||||
SCB_CPUID_IMPLEMENTER_Pos = 0x18 // Position of IMPLEMENTER field.
|
||||
SCB_CPUID_IMPLEMENTER_Msk = 0xff000000 // Bit mask of IMPLEMENTER field.
|
||||
|
||||
// ICSR: Interrupt Control and State Register
|
||||
SCB_ICSR_VECTACTIVE_Pos = 0x0 // Position of VECTACTIVE field.
|
||||
SCB_ICSR_VECTACTIVE_Msk = 0x1ff // Bit mask of VECTACTIVE field.
|
||||
SCB_ICSR_RETTOBASE_Pos = 0xb // Position of RETTOBASE field.
|
||||
SCB_ICSR_RETTOBASE_Msk = 0x800 // Bit mask of RETTOBASE field.
|
||||
SCB_ICSR_RETTOBASE = 0x800 // Bit RETTOBASE.
|
||||
SCB_ICSR_RETTOBASE_RETTOBASE_0 = 0x0 // there are preempted active exceptions to execute
|
||||
SCB_ICSR_RETTOBASE_RETTOBASE_1 = 0x1 // there are no active exceptions, or the currently-executing exception is the only active exception
|
||||
SCB_ICSR_VECTPENDING_Pos = 0xc // Position of VECTPENDING field.
|
||||
SCB_ICSR_VECTPENDING_Msk = 0x1ff000 // Bit mask of VECTPENDING field.
|
||||
SCB_ICSR_ISRPENDING_Pos = 0x16 // Position of ISRPENDING field.
|
||||
SCB_ICSR_ISRPENDING_Msk = 0x400000 // Bit mask of ISRPENDING field.
|
||||
SCB_ICSR_ISRPENDING = 0x400000 // Bit ISRPENDING.
|
||||
SCB_ICSR_ISRPENDING_ISRPENDING_0 = 0x0 // No external interrupt pending.
|
||||
SCB_ICSR_ISRPENDING_ISRPENDING_1 = 0x1 // External interrupt pending.
|
||||
SCB_ICSR_PENDSTCLR_Pos = 0x19 // Position of PENDSTCLR field.
|
||||
SCB_ICSR_PENDSTCLR_Msk = 0x2000000 // Bit mask of PENDSTCLR field.
|
||||
SCB_ICSR_PENDSTCLR = 0x2000000 // Bit PENDSTCLR.
|
||||
SCB_ICSR_PENDSTCLR_PENDSTCLR_0 = 0x0 // no effect
|
||||
SCB_ICSR_PENDSTCLR_PENDSTCLR_1 = 0x1 // removes the pending state from the SysTick exception
|
||||
SCB_ICSR_PENDSTSET_Pos = 0x1a // Position of PENDSTSET field.
|
||||
SCB_ICSR_PENDSTSET_Msk = 0x4000000 // Bit mask of PENDSTSET field.
|
||||
SCB_ICSR_PENDSTSET = 0x4000000 // Bit PENDSTSET.
|
||||
SCB_ICSR_PENDSTSET_PENDSTSET_0 = 0x0 // write: no effect; read: SysTick exception is not pending
|
||||
SCB_ICSR_PENDSTSET_PENDSTSET_1 = 0x1 // write: changes SysTick exception state to pending; read: SysTick exception is pending
|
||||
SCB_ICSR_PENDSVCLR_Pos = 0x1b // Position of PENDSVCLR field.
|
||||
SCB_ICSR_PENDSVCLR_Msk = 0x8000000 // Bit mask of PENDSVCLR field.
|
||||
SCB_ICSR_PENDSVCLR = 0x8000000 // Bit PENDSVCLR.
|
||||
SCB_ICSR_PENDSVCLR_PENDSVCLR_0 = 0x0 // no effect
|
||||
SCB_ICSR_PENDSVCLR_PENDSVCLR_1 = 0x1 // removes the pending state from the PendSV exception
|
||||
SCB_ICSR_PENDSVSET_Pos = 0x1c // Position of PENDSVSET field.
|
||||
SCB_ICSR_PENDSVSET_Msk = 0x10000000 // Bit mask of PENDSVSET field.
|
||||
SCB_ICSR_PENDSVSET = 0x10000000 // Bit PENDSVSET.
|
||||
SCB_ICSR_PENDSVSET_PENDSVSET_0 = 0x0 // write: no effect; read: PendSV exception is not pending
|
||||
SCB_ICSR_PENDSVSET_PENDSVSET_1 = 0x1 // write: changes PendSV exception state to pending; read: PendSV exception is pending
|
||||
SCB_ICSR_NMIPENDSET_Pos = 0x1f // Position of NMIPENDSET field.
|
||||
SCB_ICSR_NMIPENDSET_Msk = 0x80000000 // Bit mask of NMIPENDSET field.
|
||||
SCB_ICSR_NMIPENDSET = 0x80000000 // Bit NMIPENDSET.
|
||||
SCB_ICSR_NMIPENDSET_NMIPENDSET_0 = 0x0 // write: no effect; read: NMI exception is not pending
|
||||
SCB_ICSR_NMIPENDSET_NMIPENDSET_1 = 0x1 // write: changes NMI exception state to pending; read: NMI exception is pending
|
||||
|
||||
// VTOR: Vector Table Offset Register
|
||||
SCB_VTOR_TBLOFF_Pos = 0x7 // Position of TBLOFF field.
|
||||
SCB_VTOR_TBLOFF_Msk = 0xffffff80 // Bit mask of TBLOFF field.
|
||||
|
||||
// AIRCR: Application Interrupt and Reset Control Register
|
||||
SCB_AIRCR_VECTRESET_Pos = 0x0 // Position of VECTRESET field.
|
||||
SCB_AIRCR_VECTRESET_Msk = 0x1 // Bit mask of VECTRESET field.
|
||||
SCB_AIRCR_VECTRESET = 0x1 // Bit VECTRESET.
|
||||
SCB_AIRCR_VECTRESET_VECTRESET_0 = 0x0 // No change
|
||||
SCB_AIRCR_VECTRESET_VECTRESET_1 = 0x1 // Causes a local system reset
|
||||
SCB_AIRCR_VECTCLRACTIVE_Pos = 0x1 // Position of VECTCLRACTIVE field.
|
||||
SCB_AIRCR_VECTCLRACTIVE_Msk = 0x2 // Bit mask of VECTCLRACTIVE field.
|
||||
SCB_AIRCR_VECTCLRACTIVE = 0x2 // Bit VECTCLRACTIVE.
|
||||
SCB_AIRCR_VECTCLRACTIVE_VECTCLRACTIVE_0 = 0x0 // No change
|
||||
SCB_AIRCR_VECTCLRACTIVE_VECTCLRACTIVE_1 = 0x1 // Clears all active state information for fixed and configurable exceptions
|
||||
SCB_AIRCR_SYSRESETREQ_Pos = 0x2 // Position of SYSRESETREQ field.
|
||||
SCB_AIRCR_SYSRESETREQ_Msk = 0x4 // Bit mask of SYSRESETREQ field.
|
||||
SCB_AIRCR_SYSRESETREQ = 0x4 // Bit SYSRESETREQ.
|
||||
SCB_AIRCR_SYSRESETREQ_SYSRESETREQ_0 = 0x0 // no system reset request
|
||||
SCB_AIRCR_SYSRESETREQ_SYSRESETREQ_1 = 0x1 // asserts a signal to the outer system that requests a reset
|
||||
SCB_AIRCR_PRIGROUP_Pos = 0x8 // Position of PRIGROUP field.
|
||||
SCB_AIRCR_PRIGROUP_Msk = 0x700 // Bit mask of PRIGROUP field.
|
||||
SCB_AIRCR_ENDIANNESS_Pos = 0xf // Position of ENDIANNESS field.
|
||||
SCB_AIRCR_ENDIANNESS_Msk = 0x8000 // Bit mask of ENDIANNESS field.
|
||||
SCB_AIRCR_ENDIANNESS = 0x8000 // Bit ENDIANNESS.
|
||||
SCB_AIRCR_ENDIANNESS_ENDIANNESS_0 = 0x0 // Little-endian
|
||||
SCB_AIRCR_ENDIANNESS_ENDIANNESS_1 = 0x1 // Big-endian
|
||||
SCB_AIRCR_VECTKEY_Pos = 0x10 // Position of VECTKEY field.
|
||||
SCB_AIRCR_VECTKEY_Msk = 0xffff0000 // Bit mask of VECTKEY field.
|
||||
|
||||
// SCR: System Control Register
|
||||
SCB_SCR_SLEEPONEXIT_Pos = 0x1 // Position of SLEEPONEXIT field.
|
||||
SCB_SCR_SLEEPONEXIT_Msk = 0x2 // Bit mask of SLEEPONEXIT field.
|
||||
SCB_SCR_SLEEPONEXIT = 0x2 // Bit SLEEPONEXIT.
|
||||
SCB_SCR_SLEEPONEXIT_SLEEPONEXIT_0 = 0x0 // o not sleep when returning to Thread mode
|
||||
SCB_SCR_SLEEPONEXIT_SLEEPONEXIT_1 = 0x1 // enter sleep, or deep sleep, on return from an ISR
|
||||
SCB_SCR_SLEEPDEEP_Pos = 0x2 // Position of SLEEPDEEP field.
|
||||
SCB_SCR_SLEEPDEEP_Msk = 0x4 // Bit mask of SLEEPDEEP field.
|
||||
SCB_SCR_SLEEPDEEP = 0x4 // Bit SLEEPDEEP.
|
||||
SCB_SCR_SLEEPDEEP_SLEEPDEEP_0 = 0x0 // sleep
|
||||
SCB_SCR_SLEEPDEEP_SLEEPDEEP_1 = 0x1 // deep sleep
|
||||
SCB_SCR_SEVONPEND_Pos = 0x4 // Position of SEVONPEND field.
|
||||
SCB_SCR_SEVONPEND_Msk = 0x10 // Bit mask of SEVONPEND field.
|
||||
SCB_SCR_SEVONPEND = 0x10 // Bit SEVONPEND.
|
||||
SCB_SCR_SEVONPEND_SEVONPEND_0 = 0x0 // only enabled interrupts or events can wakeup the processor, disabled interrupts are excluded
|
||||
SCB_SCR_SEVONPEND_SEVONPEND_1 = 0x1 // enabled events and all interrupts, including disabled interrupts, can wakeup the processor
|
||||
|
||||
// CCR: Configuration and Control Register
|
||||
SCB_CCR_NONBASETHRDENA_Pos = 0x0 // Position of NONBASETHRDENA field.
|
||||
SCB_CCR_NONBASETHRDENA_Msk = 0x1 // Bit mask of NONBASETHRDENA field.
|
||||
SCB_CCR_NONBASETHRDENA = 0x1 // Bit NONBASETHRDENA.
|
||||
SCB_CCR_NONBASETHRDENA_NONBASETHRDENA_0 = 0x0 // processor can enter Thread mode only when no exception is active
|
||||
SCB_CCR_NONBASETHRDENA_NONBASETHRDENA_1 = 0x1 // processor can enter Thread mode from any level under the control of an EXC_RETURN value
|
||||
SCB_CCR_USERSETMPEND_Pos = 0x1 // Position of USERSETMPEND field.
|
||||
SCB_CCR_USERSETMPEND_Msk = 0x2 // Bit mask of USERSETMPEND field.
|
||||
SCB_CCR_USERSETMPEND = 0x2 // Bit USERSETMPEND.
|
||||
SCB_CCR_USERSETMPEND_USERSETMPEND_0 = 0x0 // disable
|
||||
SCB_CCR_USERSETMPEND_USERSETMPEND_1 = 0x1 // enable
|
||||
SCB_CCR_UNALIGN_TRP_Pos = 0x3 // Position of UNALIGN_TRP field.
|
||||
SCB_CCR_UNALIGN_TRP_Msk = 0x8 // Bit mask of UNALIGN_TRP field.
|
||||
SCB_CCR_UNALIGN_TRP = 0x8 // Bit UNALIGN_TRP.
|
||||
SCB_CCR_UNALIGN_TRP_UNALIGN_TRP_0 = 0x0 // do not trap unaligned halfword and word accesses
|
||||
SCB_CCR_UNALIGN_TRP_UNALIGN_TRP_1 = 0x1 // trap unaligned halfword and word accesses
|
||||
SCB_CCR_DIV_0_TRP_Pos = 0x4 // Position of DIV_0_TRP field.
|
||||
SCB_CCR_DIV_0_TRP_Msk = 0x10 // Bit mask of DIV_0_TRP field.
|
||||
SCB_CCR_DIV_0_TRP = 0x10 // Bit DIV_0_TRP.
|
||||
SCB_CCR_DIV_0_TRP_DIV_0_TRP_0 = 0x0 // do not trap divide by 0
|
||||
SCB_CCR_DIV_0_TRP_DIV_0_TRP_1 = 0x1 // trap divide by 0
|
||||
SCB_CCR_BFHFNMIGN_Pos = 0x8 // Position of BFHFNMIGN field.
|
||||
SCB_CCR_BFHFNMIGN_Msk = 0x100 // Bit mask of BFHFNMIGN field.
|
||||
SCB_CCR_BFHFNMIGN = 0x100 // Bit BFHFNMIGN.
|
||||
SCB_CCR_BFHFNMIGN_BFHFNMIGN_0 = 0x0 // data bus faults caused by load and store instructions cause a lock-up
|
||||
SCB_CCR_BFHFNMIGN_BFHFNMIGN_1 = 0x1 // handlers running at priority -1 and -2 ignore data bus faults caused by load and store instructions
|
||||
SCB_CCR_STKALIGN_Pos = 0x9 // Position of STKALIGN field.
|
||||
SCB_CCR_STKALIGN_Msk = 0x200 // Bit mask of STKALIGN field.
|
||||
SCB_CCR_STKALIGN = 0x200 // Bit STKALIGN.
|
||||
SCB_CCR_STKALIGN_STKALIGN_0 = 0x0 // 4-byte aligned
|
||||
SCB_CCR_STKALIGN_STKALIGN_1 = 0x1 // 8-byte aligned
|
||||
SCB_CCR_DC_Pos = 0x10 // Position of DC field.
|
||||
SCB_CCR_DC_Msk = 0x10000 // Bit mask of DC field.
|
||||
SCB_CCR_DC = 0x10000 // Bit DC.
|
||||
SCB_CCR_DC_DC_0 = 0x0 // L1 data cache disabled
|
||||
SCB_CCR_DC_DC_1 = 0x1 // L1 data cache enabled
|
||||
SCB_CCR_IC_Pos = 0x11 // Position of IC field.
|
||||
SCB_CCR_IC_Msk = 0x20000 // Bit mask of IC field.
|
||||
SCB_CCR_IC = 0x20000 // Bit IC.
|
||||
SCB_CCR_IC_IC_0 = 0x0 // L1 instruction cache disabled
|
||||
SCB_CCR_IC_IC_1 = 0x1 // L1 instruction cache enabled
|
||||
SCB_CCR_BP_Pos = 0x12 // Position of BP field.
|
||||
SCB_CCR_BP_Msk = 0x40000 // Bit mask of BP field.
|
||||
SCB_CCR_BP = 0x40000 // Bit BP.
|
||||
|
||||
// SHPR1: System Handler Priority Register 1
|
||||
SCB_SHPR1_PRI_4_Pos = 0x0 // Position of PRI_4 field.
|
||||
SCB_SHPR1_PRI_4_Msk = 0xff // Bit mask of PRI_4 field.
|
||||
SCB_SHPR1_PRI_5_Pos = 0x8 // Position of PRI_5 field.
|
||||
SCB_SHPR1_PRI_5_Msk = 0xff00 // Bit mask of PRI_5 field.
|
||||
SCB_SHPR1_PRI_6_Pos = 0x10 // Position of PRI_6 field.
|
||||
SCB_SHPR1_PRI_6_Msk = 0xff0000 // Bit mask of PRI_6 field.
|
||||
|
||||
// SHPR2: System Handler Priority Register 2
|
||||
SCB_SHPR2_PRI_11_Pos = 0x18 // Position of PRI_11 field.
|
||||
SCB_SHPR2_PRI_11_Msk = 0xff000000 // Bit mask of PRI_11 field.
|
||||
|
||||
// SHPR3: System Handler Priority Register 3
|
||||
SCB_SHPR3_PRI_14_Pos = 0x10 // Position of PRI_14 field.
|
||||
SCB_SHPR3_PRI_14_Msk = 0xff0000 // Bit mask of PRI_14 field.
|
||||
SCB_SHPR3_PRI_15_Pos = 0x18 // Position of PRI_15 field.
|
||||
SCB_SHPR3_PRI_15_Msk = 0xff000000 // Bit mask of PRI_15 field.
|
||||
|
||||
// SHCSR: System Handler Control and State Register
|
||||
SCB_SHCSR_MEMFAULTACT_Pos = 0x0 // Position of MEMFAULTACT field.
|
||||
SCB_SHCSR_MEMFAULTACT_Msk = 0x1 // Bit mask of MEMFAULTACT field.
|
||||
SCB_SHCSR_MEMFAULTACT = 0x1 // Bit MEMFAULTACT.
|
||||
SCB_SHCSR_MEMFAULTACT_MEMFAULTACT_0 = 0x0 // exception is not active
|
||||
SCB_SHCSR_MEMFAULTACT_MEMFAULTACT_1 = 0x1 // exception is active
|
||||
SCB_SHCSR_BUSFAULTACT_Pos = 0x1 // Position of BUSFAULTACT field.
|
||||
SCB_SHCSR_BUSFAULTACT_Msk = 0x2 // Bit mask of BUSFAULTACT field.
|
||||
SCB_SHCSR_BUSFAULTACT = 0x2 // Bit BUSFAULTACT.
|
||||
SCB_SHCSR_BUSFAULTACT_BUSFAULTACT_0 = 0x0 // exception is not active
|
||||
SCB_SHCSR_BUSFAULTACT_BUSFAULTACT_1 = 0x1 // exception is active
|
||||
SCB_SHCSR_USGFAULTACT_Pos = 0x3 // Position of USGFAULTACT field.
|
||||
SCB_SHCSR_USGFAULTACT_Msk = 0x8 // Bit mask of USGFAULTACT field.
|
||||
SCB_SHCSR_USGFAULTACT = 0x8 // Bit USGFAULTACT.
|
||||
SCB_SHCSR_USGFAULTACT_USGFAULTACT_0 = 0x0 // exception is not active
|
||||
SCB_SHCSR_USGFAULTACT_USGFAULTACT_1 = 0x1 // exception is active
|
||||
SCB_SHCSR_SVCALLACT_Pos = 0x7 // Position of SVCALLACT field.
|
||||
SCB_SHCSR_SVCALLACT_Msk = 0x80 // Bit mask of SVCALLACT field.
|
||||
SCB_SHCSR_SVCALLACT = 0x80 // Bit SVCALLACT.
|
||||
SCB_SHCSR_SVCALLACT_SVCALLACT_0 = 0x0 // exception is not active
|
||||
SCB_SHCSR_SVCALLACT_SVCALLACT_1 = 0x1 // exception is active
|
||||
SCB_SHCSR_MONITORACT_Pos = 0x8 // Position of MONITORACT field.
|
||||
SCB_SHCSR_MONITORACT_Msk = 0x100 // Bit mask of MONITORACT field.
|
||||
SCB_SHCSR_MONITORACT = 0x100 // Bit MONITORACT.
|
||||
SCB_SHCSR_MONITORACT_MONITORACT_0 = 0x0 // exception is not active
|
||||
SCB_SHCSR_MONITORACT_MONITORACT_1 = 0x1 // exception is active
|
||||
SCB_SHCSR_PENDSVACT_Pos = 0xa // Position of PENDSVACT field.
|
||||
SCB_SHCSR_PENDSVACT_Msk = 0x400 // Bit mask of PENDSVACT field.
|
||||
SCB_SHCSR_PENDSVACT = 0x400 // Bit PENDSVACT.
|
||||
SCB_SHCSR_PENDSVACT_PENDSVACT_0 = 0x0 // exception is not active
|
||||
SCB_SHCSR_PENDSVACT_PENDSVACT_1 = 0x1 // exception is active
|
||||
SCB_SHCSR_SYSTICKACT_Pos = 0xb // Position of SYSTICKACT field.
|
||||
SCB_SHCSR_SYSTICKACT_Msk = 0x800 // Bit mask of SYSTICKACT field.
|
||||
SCB_SHCSR_SYSTICKACT = 0x800 // Bit SYSTICKACT.
|
||||
SCB_SHCSR_SYSTICKACT_SYSTICKACT_0 = 0x0 // exception is not active
|
||||
SCB_SHCSR_SYSTICKACT_SYSTICKACT_1 = 0x1 // exception is active
|
||||
SCB_SHCSR_USGFAULTPENDED_Pos = 0xc // Position of USGFAULTPENDED field.
|
||||
SCB_SHCSR_USGFAULTPENDED_Msk = 0x1000 // Bit mask of USGFAULTPENDED field.
|
||||
SCB_SHCSR_USGFAULTPENDED = 0x1000 // Bit USGFAULTPENDED.
|
||||
SCB_SHCSR_USGFAULTPENDED_USGFAULTPENDED_0 = 0x0 // exception is not pending
|
||||
SCB_SHCSR_USGFAULTPENDED_USGFAULTPENDED_1 = 0x1 // exception is pending
|
||||
SCB_SHCSR_MEMFAULTPENDED_Pos = 0xd // Position of MEMFAULTPENDED field.
|
||||
SCB_SHCSR_MEMFAULTPENDED_Msk = 0x2000 // Bit mask of MEMFAULTPENDED field.
|
||||
SCB_SHCSR_MEMFAULTPENDED = 0x2000 // Bit MEMFAULTPENDED.
|
||||
SCB_SHCSR_MEMFAULTPENDED_MEMFAULTPENDED_0 = 0x0 // exception is not pending
|
||||
SCB_SHCSR_MEMFAULTPENDED_MEMFAULTPENDED_1 = 0x1 // exception is pending
|
||||
SCB_SHCSR_BUSFAULTPENDED_Pos = 0xe // Position of BUSFAULTPENDED field.
|
||||
SCB_SHCSR_BUSFAULTPENDED_Msk = 0x4000 // Bit mask of BUSFAULTPENDED field.
|
||||
SCB_SHCSR_BUSFAULTPENDED = 0x4000 // Bit BUSFAULTPENDED.
|
||||
SCB_SHCSR_BUSFAULTPENDED_BUSFAULTPENDED_0 = 0x0 // exception is not pending
|
||||
SCB_SHCSR_BUSFAULTPENDED_BUSFAULTPENDED_1 = 0x1 // exception is pending
|
||||
SCB_SHCSR_SVCALLPENDED_Pos = 0xf // Position of SVCALLPENDED field.
|
||||
SCB_SHCSR_SVCALLPENDED_Msk = 0x8000 // Bit mask of SVCALLPENDED field.
|
||||
SCB_SHCSR_SVCALLPENDED = 0x8000 // Bit SVCALLPENDED.
|
||||
SCB_SHCSR_SVCALLPENDED_SVCALLPENDED_0 = 0x0 // exception is not pending
|
||||
SCB_SHCSR_SVCALLPENDED_SVCALLPENDED_1 = 0x1 // exception is pending
|
||||
SCB_SHCSR_MEMFAULTENA_Pos = 0x10 // Position of MEMFAULTENA field.
|
||||
SCB_SHCSR_MEMFAULTENA_Msk = 0x10000 // Bit mask of MEMFAULTENA field.
|
||||
SCB_SHCSR_MEMFAULTENA = 0x10000 // Bit MEMFAULTENA.
|
||||
SCB_SHCSR_MEMFAULTENA_MEMFAULTENA_0 = 0x0 // disable the exception
|
||||
SCB_SHCSR_MEMFAULTENA_MEMFAULTENA_1 = 0x1 // enable the exception
|
||||
SCB_SHCSR_BUSFAULTENA_Pos = 0x11 // Position of BUSFAULTENA field.
|
||||
SCB_SHCSR_BUSFAULTENA_Msk = 0x20000 // Bit mask of BUSFAULTENA field.
|
||||
SCB_SHCSR_BUSFAULTENA = 0x20000 // Bit BUSFAULTENA.
|
||||
SCB_SHCSR_BUSFAULTENA_BUSFAULTENA_0 = 0x0 // disable the exception
|
||||
SCB_SHCSR_BUSFAULTENA_BUSFAULTENA_1 = 0x1 // enable the exception
|
||||
SCB_SHCSR_USGFAULTENA_Pos = 0x12 // Position of USGFAULTENA field.
|
||||
SCB_SHCSR_USGFAULTENA_Msk = 0x40000 // Bit mask of USGFAULTENA field.
|
||||
SCB_SHCSR_USGFAULTENA = 0x40000 // Bit USGFAULTENA.
|
||||
SCB_SHCSR_USGFAULTENA_USGFAULTENA_0 = 0x0 // disable the exception
|
||||
SCB_SHCSR_USGFAULTENA_USGFAULTENA_1 = 0x1 // enable the exception
|
||||
|
||||
// CFSR: Configurable Fault Status Register
|
||||
SCB_CFSR_IACCVIOL_Pos = 0x0 // Position of IACCVIOL field.
|
||||
SCB_CFSR_IACCVIOL_Msk = 0x1 // Bit mask of IACCVIOL field.
|
||||
SCB_CFSR_IACCVIOL = 0x1 // Bit IACCVIOL.
|
||||
SCB_CFSR_IACCVIOL_IACCVIOL_0 = 0x0 // no instruction access violation fault
|
||||
SCB_CFSR_IACCVIOL_IACCVIOL_1 = 0x1 // the processor attempted an instruction fetch from a location that does not permit execution
|
||||
SCB_CFSR_DACCVIOL_Pos = 0x1 // Position of DACCVIOL field.
|
||||
SCB_CFSR_DACCVIOL_Msk = 0x2 // Bit mask of DACCVIOL field.
|
||||
SCB_CFSR_DACCVIOL = 0x2 // Bit DACCVIOL.
|
||||
SCB_CFSR_DACCVIOL_DACCVIOL_0 = 0x0 // no data access violation fault
|
||||
SCB_CFSR_DACCVIOL_DACCVIOL_1 = 0x1 // the processor attempted a load or store at a location that does not permit the operation
|
||||
SCB_CFSR_MUNSTKERR_Pos = 0x3 // Position of MUNSTKERR field.
|
||||
SCB_CFSR_MUNSTKERR_Msk = 0x8 // Bit mask of MUNSTKERR field.
|
||||
SCB_CFSR_MUNSTKERR = 0x8 // Bit MUNSTKERR.
|
||||
SCB_CFSR_MUNSTKERR_MUNSTKERR_0 = 0x0 // no unstacking fault
|
||||
SCB_CFSR_MUNSTKERR_MUNSTKERR_1 = 0x1 // unstack for an exception return has caused one or more access violations
|
||||
SCB_CFSR_MSTKERR_Pos = 0x4 // Position of MSTKERR field.
|
||||
SCB_CFSR_MSTKERR_Msk = 0x10 // Bit mask of MSTKERR field.
|
||||
SCB_CFSR_MSTKERR = 0x10 // Bit MSTKERR.
|
||||
SCB_CFSR_MSTKERR_MSTKERR_0 = 0x0 // no stacking fault
|
||||
SCB_CFSR_MSTKERR_MSTKERR_1 = 0x1 // stacking for an exception entry has caused one or more access violations
|
||||
SCB_CFSR_MLSPERR_Pos = 0x5 // Position of MLSPERR field.
|
||||
SCB_CFSR_MLSPERR_Msk = 0x20 // Bit mask of MLSPERR field.
|
||||
SCB_CFSR_MLSPERR = 0x20 // Bit MLSPERR.
|
||||
SCB_CFSR_MLSPERR_MLSPERR_0 = 0x0 // No MemManage fault occurred during floating-point lazy state preservation
|
||||
SCB_CFSR_MLSPERR_MLSPERR_1 = 0x1 // A MemManage fault occurred during floating-point lazy state preservation
|
||||
SCB_CFSR_MMARVALID_Pos = 0x7 // Position of MMARVALID field.
|
||||
SCB_CFSR_MMARVALID_Msk = 0x80 // Bit mask of MMARVALID field.
|
||||
SCB_CFSR_MMARVALID = 0x80 // Bit MMARVALID.
|
||||
SCB_CFSR_MMARVALID_MMARVALID_0 = 0x0 // value in MMAR is not a valid fault address
|
||||
SCB_CFSR_MMARVALID_MMARVALID_1 = 0x1 // MMAR holds a valid fault address
|
||||
SCB_CFSR_IBUSERR_Pos = 0x8 // Position of IBUSERR field.
|
||||
SCB_CFSR_IBUSERR_Msk = 0x100 // Bit mask of IBUSERR field.
|
||||
SCB_CFSR_IBUSERR = 0x100 // Bit IBUSERR.
|
||||
SCB_CFSR_IBUSERR_IBUSERR_0 = 0x0 // no instruction bus error
|
||||
SCB_CFSR_IBUSERR_IBUSERR_1 = 0x1 // instruction bus error
|
||||
SCB_CFSR_PRECISERR_Pos = 0x9 // Position of PRECISERR field.
|
||||
SCB_CFSR_PRECISERR_Msk = 0x200 // Bit mask of PRECISERR field.
|
||||
SCB_CFSR_PRECISERR = 0x200 // Bit PRECISERR.
|
||||
SCB_CFSR_PRECISERR_PRECISERR_0 = 0x0 // no precise data bus error
|
||||
SCB_CFSR_PRECISERR_PRECISERR_1 = 0x1 // a data bus error has occurred, and the PC value stacked for the exception return points to the instruction that caused the fault
|
||||
SCB_CFSR_IMPRECISERR_Pos = 0xa // Position of IMPRECISERR field.
|
||||
SCB_CFSR_IMPRECISERR_Msk = 0x400 // Bit mask of IMPRECISERR field.
|
||||
SCB_CFSR_IMPRECISERR = 0x400 // Bit IMPRECISERR.
|
||||
SCB_CFSR_IMPRECISERR_IMPRECISERR_0 = 0x0 // no imprecise data bus error
|
||||
SCB_CFSR_IMPRECISERR_IMPRECISERR_1 = 0x1 // a data bus error has occurred, but the return address in the stack frame is not related to the instruction that caused the error
|
||||
SCB_CFSR_UNSTKERR_Pos = 0xb // Position of UNSTKERR field.
|
||||
SCB_CFSR_UNSTKERR_Msk = 0x800 // Bit mask of UNSTKERR field.
|
||||
SCB_CFSR_UNSTKERR = 0x800 // Bit UNSTKERR.
|
||||
SCB_CFSR_UNSTKERR_UNSTKERR_0 = 0x0 // no unstacking fault
|
||||
SCB_CFSR_UNSTKERR_UNSTKERR_1 = 0x1 // unstack for an exception return has caused one or more BusFaults
|
||||
SCB_CFSR_STKERR_Pos = 0xc // Position of STKERR field.
|
||||
SCB_CFSR_STKERR_Msk = 0x1000 // Bit mask of STKERR field.
|
||||
SCB_CFSR_STKERR = 0x1000 // Bit STKERR.
|
||||
SCB_CFSR_STKERR_STKERR_0 = 0x0 // no stacking fault
|
||||
SCB_CFSR_STKERR_STKERR_1 = 0x1 // stacking for an exception entry has caused one or more BusFaults
|
||||
SCB_CFSR_LSPERR_Pos = 0xd // Position of LSPERR field.
|
||||
SCB_CFSR_LSPERR_Msk = 0x2000 // Bit mask of LSPERR field.
|
||||
SCB_CFSR_LSPERR = 0x2000 // Bit LSPERR.
|
||||
SCB_CFSR_LSPERR_LSPERR_0 = 0x0 // No bus fault occurred during floating-point lazy state preservation
|
||||
SCB_CFSR_LSPERR_LSPERR_1 = 0x1 // A bus fault occurred during floating-point lazy state preservation
|
||||
SCB_CFSR_BFARVALID_Pos = 0xf // Position of BFARVALID field.
|
||||
SCB_CFSR_BFARVALID_Msk = 0x8000 // Bit mask of BFARVALID field.
|
||||
SCB_CFSR_BFARVALID = 0x8000 // Bit BFARVALID.
|
||||
SCB_CFSR_BFARVALID_BFARVALID_0 = 0x0 // value in BFAR is not a valid fault address
|
||||
SCB_CFSR_BFARVALID_BFARVALID_1 = 0x1 // BFAR holds a valid fault address
|
||||
SCB_CFSR_UNDEFINSTR_Pos = 0x10 // Position of UNDEFINSTR field.
|
||||
SCB_CFSR_UNDEFINSTR_Msk = 0x10000 // Bit mask of UNDEFINSTR field.
|
||||
SCB_CFSR_UNDEFINSTR = 0x10000 // Bit UNDEFINSTR.
|
||||
SCB_CFSR_UNDEFINSTR_UNDEFINSTR_0 = 0x0 // no undefined instruction UsageFault
|
||||
SCB_CFSR_UNDEFINSTR_UNDEFINSTR_1 = 0x1 // the processor has attempted to execute an undefined instruction
|
||||
SCB_CFSR_INVSTATE_Pos = 0x11 // Position of INVSTATE field.
|
||||
SCB_CFSR_INVSTATE_Msk = 0x20000 // Bit mask of INVSTATE field.
|
||||
SCB_CFSR_INVSTATE = 0x20000 // Bit INVSTATE.
|
||||
SCB_CFSR_INVSTATE_INVSTATE_0 = 0x0 // no invalid state UsageFault
|
||||
SCB_CFSR_INVSTATE_INVSTATE_1 = 0x1 // the processor has attempted to execute an instruction that makes illegal use of the EPSR
|
||||
SCB_CFSR_INVPC_Pos = 0x12 // Position of INVPC field.
|
||||
SCB_CFSR_INVPC_Msk = 0x40000 // Bit mask of INVPC field.
|
||||
SCB_CFSR_INVPC = 0x40000 // Bit INVPC.
|
||||
SCB_CFSR_INVPC_INVPC_0 = 0x0 // no invalid PC load UsageFault
|
||||
SCB_CFSR_INVPC_INVPC_1 = 0x1 // the processor has attempted an illegal load of EXC_RETURN to the PC
|
||||
SCB_CFSR_NOCP_Pos = 0x13 // Position of NOCP field.
|
||||
SCB_CFSR_NOCP_Msk = 0x80000 // Bit mask of NOCP field.
|
||||
SCB_CFSR_NOCP = 0x80000 // Bit NOCP.
|
||||
SCB_CFSR_NOCP_NOCP_0 = 0x0 // no UsageFault caused by attempting to access a coprocessor
|
||||
SCB_CFSR_NOCP_NOCP_1 = 0x1 // the processor has attempted to access a coprocessor
|
||||
SCB_CFSR_UNALIGNED_Pos = 0x18 // Position of UNALIGNED field.
|
||||
SCB_CFSR_UNALIGNED_Msk = 0x1000000 // Bit mask of UNALIGNED field.
|
||||
SCB_CFSR_UNALIGNED = 0x1000000 // Bit UNALIGNED.
|
||||
SCB_CFSR_UNALIGNED_UNALIGNED_0 = 0x0 // no unaligned access fault, or unaligned access trapping not enabled
|
||||
SCB_CFSR_UNALIGNED_UNALIGNED_1 = 0x1 // the processor has made an unaligned memory access
|
||||
SCB_CFSR_DIVBYZERO_Pos = 0x19 // Position of DIVBYZERO field.
|
||||
SCB_CFSR_DIVBYZERO_Msk = 0x2000000 // Bit mask of DIVBYZERO field.
|
||||
SCB_CFSR_DIVBYZERO = 0x2000000 // Bit DIVBYZERO.
|
||||
SCB_CFSR_DIVBYZERO_DIVBYZERO_0 = 0x0 // no divide by zero fault, or divide by zero trapping not enabled
|
||||
SCB_CFSR_DIVBYZERO_DIVBYZERO_1 = 0x1 // the processor has executed an SDIV or UDIV instruction with a divisor of 0
|
||||
|
||||
// HFSR: HardFault Status register
|
||||
SCB_HFSR_VECTTBL_Pos = 0x1 // Position of VECTTBL field.
|
||||
SCB_HFSR_VECTTBL_Msk = 0x2 // Bit mask of VECTTBL field.
|
||||
SCB_HFSR_VECTTBL = 0x2 // Bit VECTTBL.
|
||||
SCB_HFSR_VECTTBL_VECTTBL_0 = 0x0 // no BusFault on vector table read
|
||||
SCB_HFSR_VECTTBL_VECTTBL_1 = 0x1 // BusFault on vector table read
|
||||
SCB_HFSR_FORCED_Pos = 0x1e // Position of FORCED field.
|
||||
SCB_HFSR_FORCED_Msk = 0x40000000 // Bit mask of FORCED field.
|
||||
SCB_HFSR_FORCED = 0x40000000 // Bit FORCED.
|
||||
SCB_HFSR_FORCED_FORCED_0 = 0x0 // no forced HardFault
|
||||
SCB_HFSR_FORCED_FORCED_1 = 0x1 // forced HardFault
|
||||
SCB_HFSR_DEBUGEVT_Pos = 0x1f // Position of DEBUGEVT field.
|
||||
SCB_HFSR_DEBUGEVT_Msk = 0x80000000 // Bit mask of DEBUGEVT field.
|
||||
SCB_HFSR_DEBUGEVT = 0x80000000 // Bit DEBUGEVT.
|
||||
SCB_HFSR_DEBUGEVT_DEBUGEVT_0 = 0x0 // No Debug event has occurred.
|
||||
SCB_HFSR_DEBUGEVT_DEBUGEVT_1 = 0x1 // Debug event has occurred. The Debug Fault Status Register has been updated.
|
||||
|
||||
// DFSR: Debug Fault Status Register
|
||||
SCB_DFSR_HALTED_Pos = 0x0 // Position of HALTED field.
|
||||
SCB_DFSR_HALTED_Msk = 0x1 // Bit mask of HALTED field.
|
||||
SCB_DFSR_HALTED = 0x1 // Bit HALTED.
|
||||
SCB_DFSR_HALTED_HALTED_0 = 0x0 // No active halt request debug event
|
||||
SCB_DFSR_HALTED_HALTED_1 = 0x1 // Halt request debug event active
|
||||
SCB_DFSR_BKPT_Pos = 0x1 // Position of BKPT field.
|
||||
SCB_DFSR_BKPT_Msk = 0x2 // Bit mask of BKPT field.
|
||||
SCB_DFSR_BKPT = 0x2 // Bit BKPT.
|
||||
SCB_DFSR_BKPT_BKPT_0 = 0x0 // No current breakpoint debug event
|
||||
SCB_DFSR_BKPT_BKPT_1 = 0x1 // At least one current breakpoint debug event
|
||||
SCB_DFSR_DWTTRAP_Pos = 0x2 // Position of DWTTRAP field.
|
||||
SCB_DFSR_DWTTRAP_Msk = 0x4 // Bit mask of DWTTRAP field.
|
||||
SCB_DFSR_DWTTRAP = 0x4 // Bit DWTTRAP.
|
||||
SCB_DFSR_DWTTRAP_DWTTRAP_0 = 0x0 // No current debug events generated by the DWT
|
||||
SCB_DFSR_DWTTRAP_DWTTRAP_1 = 0x1 // At least one current debug event generated by the DWT
|
||||
SCB_DFSR_VCATCH_Pos = 0x3 // Position of VCATCH field.
|
||||
SCB_DFSR_VCATCH_Msk = 0x8 // Bit mask of VCATCH field.
|
||||
SCB_DFSR_VCATCH = 0x8 // Bit VCATCH.
|
||||
SCB_DFSR_VCATCH_VCATCH_0 = 0x0 // No Vector catch triggered
|
||||
SCB_DFSR_VCATCH_VCATCH_1 = 0x1 // Vector catch triggered
|
||||
SCB_DFSR_EXTERNAL_Pos = 0x4 // Position of EXTERNAL field.
|
||||
SCB_DFSR_EXTERNAL_Msk = 0x10 // Bit mask of EXTERNAL field.
|
||||
SCB_DFSR_EXTERNAL = 0x10 // Bit EXTERNAL.
|
||||
SCB_DFSR_EXTERNAL_EXTERNAL_0 = 0x0 // No external debug request debug event
|
||||
SCB_DFSR_EXTERNAL_EXTERNAL_1 = 0x1 // External debug request debug event
|
||||
|
||||
// MMFAR: MemManage Fault Address Register
|
||||
SCB_MMFAR_ADDRESS_Pos = 0x0 // Position of ADDRESS field.
|
||||
SCB_MMFAR_ADDRESS_Msk = 0xffffffff // Bit mask of ADDRESS field.
|
||||
|
||||
// BFAR: BusFault Address Register
|
||||
SCB_BFAR_ADDRESS_Pos = 0x0 // Position of ADDRESS field.
|
||||
SCB_BFAR_ADDRESS_Msk = 0xffffffff // Bit mask of ADDRESS field.
|
||||
)
|
||||
@@ -0,0 +1,36 @@
|
||||
package arm64
|
||||
|
||||
// Run the given assembly code. The code will be marked as having side effects,
|
||||
// as it doesn't produce output and thus would normally be eliminated by the
|
||||
// optimizer.
|
||||
func Asm(asm string)
|
||||
|
||||
// Run the given inline assembly. The code will be marked as having side
|
||||
// effects, as it would otherwise be optimized away. The inline assembly string
|
||||
// recognizes template values in the form {name}, like so:
|
||||
//
|
||||
// arm.AsmFull(
|
||||
// "str {value}, {result}",
|
||||
// map[string]interface{}{
|
||||
// "value": 1
|
||||
// "result": &dest,
|
||||
// })
|
||||
//
|
||||
// You can use {} in the asm string (which expands to a register) to set the
|
||||
// return value.
|
||||
func AsmFull(asm string, regs map[string]interface{}) uintptr
|
||||
|
||||
// Run the following system call (SVCall) with 0 arguments.
|
||||
func SVCall0(num uintptr) uintptr
|
||||
|
||||
// Run the following system call (SVCall) with 1 argument.
|
||||
func SVCall1(num uintptr, a1 interface{}) uintptr
|
||||
|
||||
// Run the following system call (SVCall) with 2 arguments.
|
||||
func SVCall2(num uintptr, a1, a2 interface{}) uintptr
|
||||
|
||||
// Run the following system call (SVCall) with 3 arguments.
|
||||
func SVCall3(num uintptr, a1, a2, a3 interface{}) uintptr
|
||||
|
||||
// Run the following system call (SVCall) with 4 arguments.
|
||||
func SVCall4(num uintptr, a1, a2, a3, a4 interface{}) uintptr
|
||||
@@ -0,0 +1,29 @@
|
||||
// Hand created file. DO NOT DELETE.
|
||||
// Hardfault aliases for definitions that have inconsistent naming (which are
|
||||
// auto-generated by gen-device-svd.go) among devices in package nxp.
|
||||
|
||||
// +build nxp,!mimxrt1062
|
||||
|
||||
package nxp
|
||||
|
||||
const (
|
||||
HardFault_CFSR_IACCVIOL = SystemControl_CFSR_IACCVIOL
|
||||
HardFault_CFSR_DACCVIOL = SystemControl_CFSR_DACCVIOL
|
||||
HardFault_CFSR_MUNSTKERR = SystemControl_CFSR_MUNSTKERR
|
||||
HardFault_CFSR_MSTKERR = SystemControl_CFSR_MSTKERR
|
||||
HardFault_CFSR_MLSPERR = SystemControl_CFSR_MLSPERR
|
||||
HardFault_CFSR_IBUSERR = SystemControl_CFSR_IBUSERR
|
||||
HardFault_CFSR_PRECISERR = SystemControl_CFSR_PRECISERR
|
||||
HardFault_CFSR_IMPRECISERR = SystemControl_CFSR_IMPRECISERR
|
||||
HardFault_CFSR_UNSTKERR = SystemControl_CFSR_UNSTKERR
|
||||
HardFault_CFSR_STKERR = SystemControl_CFSR_STKERR
|
||||
HardFault_CFSR_LSPERR = SystemControl_CFSR_LSPERR
|
||||
HardFault_CFSR_UNDEFINSTR = SystemControl_CFSR_UNDEFINSTR
|
||||
HardFault_CFSR_INVSTATE = SystemControl_CFSR_INVSTATE
|
||||
HardFault_CFSR_INVPC = SystemControl_CFSR_INVPC
|
||||
HardFault_CFSR_NOCP = SystemControl_CFSR_NOCP
|
||||
HardFault_CFSR_UNALIGNED = SystemControl_CFSR_UNALIGNED
|
||||
HardFault_CFSR_DIVBYZERO = SystemControl_CFSR_DIVBYZERO
|
||||
HardFault_CFSR_MMARVALID = SystemControl_CFSR_MMARVALID
|
||||
HardFault_CFSR_BFARVALID = SystemControl_CFSR_BFARVALID
|
||||
)
|
||||
@@ -0,0 +1,529 @@
|
||||
// Hand created file. DO NOT DELETE.
|
||||
// Type definitions, fields, and constants associated with various clocks and
|
||||
// peripherals of the NXP MIMXRT1062.
|
||||
|
||||
// +build nxp,mimxrt1062
|
||||
|
||||
package nxp
|
||||
|
||||
import (
|
||||
"runtime/volatile"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Clock represents an individual peripheral clock that may be enabled/disabled
|
||||
// at runtime. Clocks also have a method `Mux` for selecting the clock source
|
||||
// and a method `Div` for selecting the hardware divisor. Note that many
|
||||
// peripherals have an independent prescalar configuration applied to the output
|
||||
// of this divisor.
|
||||
type (
|
||||
Clock uint32
|
||||
ClockMode uint8
|
||||
)
|
||||
|
||||
// Enable activates or deactivates the clock gate of receiver Clock c.
|
||||
func (c Clock) Enable(enable bool) {
|
||||
if enable {
|
||||
c.setGate(clockNeededRunWait)
|
||||
} else {
|
||||
c.setGate(clockNotNeeded)
|
||||
}
|
||||
}
|
||||
|
||||
// Mux selects a clock source for the mux of the receiver Clock c.
|
||||
func (c Clock) Mux(mux uint32) { c.setCcm(mux) }
|
||||
|
||||
// Div configures the prescalar divisor of the receiver Clock c.
|
||||
func (c Clock) Div(div uint32) { c.setCcm(div) }
|
||||
|
||||
const (
|
||||
ClockModeRun ClockMode = 0 // Remain in run mode
|
||||
ClockModeWait ClockMode = 1 // Transfer to wait mode
|
||||
ClockModeStop ClockMode = 2 // Transfer to stop mode
|
||||
)
|
||||
|
||||
// Set configures the run mode of the MCU.
|
||||
func (m ClockMode) Set() {
|
||||
CCM.CLPCR.Set((CCM.CLPCR.Get() & ^uint32(CCM_CLPCR_LPM_Msk)) |
|
||||
((uint32(m) << CCM_CLPCR_LPM_Pos) & CCM_CLPCR_LPM_Msk))
|
||||
}
|
||||
|
||||
// Named oscillators
|
||||
const (
|
||||
ClockCpu Clock = 0x0 // CPU clock
|
||||
ClockAhb Clock = 0x1 // AHB clock
|
||||
ClockSemc Clock = 0x2 // SEMC clock
|
||||
ClockIpg Clock = 0x3 // IPG clock
|
||||
ClockPer Clock = 0x4 // PER clock
|
||||
ClockOsc Clock = 0x5 // OSC clock selected by PMU_LOWPWR_CTRL[OSC_SEL]
|
||||
ClockRtc Clock = 0x6 // RTC clock (RTCCLK)
|
||||
ClockArmPll Clock = 0x7 // ARMPLLCLK
|
||||
ClockUsb1Pll Clock = 0x8 // USB1PLLCLK
|
||||
ClockUsb1PllPfd0 Clock = 0x9 // USB1PLLPDF0CLK
|
||||
ClockUsb1PllPfd1 Clock = 0xA // USB1PLLPFD1CLK
|
||||
ClockUsb1PllPfd2 Clock = 0xB // USB1PLLPFD2CLK
|
||||
ClockUsb1PllPfd3 Clock = 0xC // USB1PLLPFD3CLK
|
||||
ClockUsb2Pll Clock = 0xD // USB2PLLCLK
|
||||
ClockSysPll Clock = 0xE // SYSPLLCLK
|
||||
ClockSysPllPfd0 Clock = 0xF // SYSPLLPDF0CLK
|
||||
ClockSysPllPfd1 Clock = 0x10 // SYSPLLPFD1CLK
|
||||
ClockSysPllPfd2 Clock = 0x11 // SYSPLLPFD2CLK
|
||||
ClockSysPllPfd3 Clock = 0x12 // SYSPLLPFD3CLK
|
||||
ClockEnetPll0 Clock = 0x13 // Enet PLLCLK ref_enetpll0
|
||||
ClockEnetPll1 Clock = 0x14 // Enet PLLCLK ref_enetpll1
|
||||
ClockEnetPll2 Clock = 0x15 // Enet PLLCLK ref_enetpll2
|
||||
ClockAudioPll Clock = 0x16 // Audio PLLCLK
|
||||
ClockVideoPll Clock = 0x17 // Video PLLCLK
|
||||
)
|
||||
|
||||
// Named clocks of integrated peripherals
|
||||
const (
|
||||
ClockIpAipsTz1 Clock = (0 << 8) | CCM_CCGR0_CG0_Pos // CCGR0, CG0
|
||||
ClockIpAipsTz2 Clock = (0 << 8) | CCM_CCGR0_CG1_Pos // CCGR0, CG1
|
||||
ClockIpMqs Clock = (0 << 8) | CCM_CCGR0_CG2_Pos // CCGR0, CG2
|
||||
ClockIpFlexSpiExsc Clock = (0 << 8) | CCM_CCGR0_CG3_Pos // CCGR0, CG3
|
||||
ClockIpSimMMain Clock = (0 << 8) | CCM_CCGR0_CG4_Pos // CCGR0, CG4
|
||||
ClockIpDcp Clock = (0 << 8) | CCM_CCGR0_CG5_Pos // CCGR0, CG5
|
||||
ClockIpLpuart3 Clock = (0 << 8) | CCM_CCGR0_CG6_Pos // CCGR0, CG6
|
||||
ClockIpCan1 Clock = (0 << 8) | CCM_CCGR0_CG7_Pos // CCGR0, CG7
|
||||
ClockIpCan1S Clock = (0 << 8) | CCM_CCGR0_CG8_Pos // CCGR0, CG8
|
||||
ClockIpCan2 Clock = (0 << 8) | CCM_CCGR0_CG9_Pos // CCGR0, CG9
|
||||
ClockIpCan2S Clock = (0 << 8) | CCM_CCGR0_CG10_Pos // CCGR0, CG10
|
||||
ClockIpTrace Clock = (0 << 8) | CCM_CCGR0_CG11_Pos // CCGR0, CG11
|
||||
ClockIpGpt2 Clock = (0 << 8) | CCM_CCGR0_CG12_Pos // CCGR0, CG12
|
||||
ClockIpGpt2S Clock = (0 << 8) | CCM_CCGR0_CG13_Pos // CCGR0, CG13
|
||||
ClockIpLpuart2 Clock = (0 << 8) | CCM_CCGR0_CG14_Pos // CCGR0, CG14
|
||||
ClockIpGpio2 Clock = (0 << 8) | CCM_CCGR0_CG15_Pos // CCGR0, CG15
|
||||
|
||||
ClockIpLpspi1 Clock = (1 << 8) | CCM_CCGR1_CG0_Pos // CCGR1, CG0
|
||||
ClockIpLpspi2 Clock = (1 << 8) | CCM_CCGR1_CG1_Pos // CCGR1, CG1
|
||||
ClockIpLpspi3 Clock = (1 << 8) | CCM_CCGR1_CG2_Pos // CCGR1, CG2
|
||||
ClockIpLpspi4 Clock = (1 << 8) | CCM_CCGR1_CG3_Pos // CCGR1, CG3
|
||||
ClockIpAdc2 Clock = (1 << 8) | CCM_CCGR1_CG4_Pos // CCGR1, CG4
|
||||
ClockIpEnet Clock = (1 << 8) | CCM_CCGR1_CG5_Pos // CCGR1, CG5
|
||||
ClockIpPit Clock = (1 << 8) | CCM_CCGR1_CG6_Pos // CCGR1, CG6
|
||||
ClockIpAoi2 Clock = (1 << 8) | CCM_CCGR1_CG7_Pos // CCGR1, CG7
|
||||
ClockIpAdc1 Clock = (1 << 8) | CCM_CCGR1_CG8_Pos // CCGR1, CG8
|
||||
ClockIpSemcExsc Clock = (1 << 8) | CCM_CCGR1_CG9_Pos // CCGR1, CG9
|
||||
ClockIpGpt1 Clock = (1 << 8) | CCM_CCGR1_CG10_Pos // CCGR1, CG10
|
||||
ClockIpGpt1S Clock = (1 << 8) | CCM_CCGR1_CG11_Pos // CCGR1, CG11
|
||||
ClockIpLpuart4 Clock = (1 << 8) | CCM_CCGR1_CG12_Pos // CCGR1, CG12
|
||||
ClockIpGpio1 Clock = (1 << 8) | CCM_CCGR1_CG13_Pos // CCGR1, CG13
|
||||
ClockIpCsu Clock = (1 << 8) | CCM_CCGR1_CG14_Pos // CCGR1, CG14
|
||||
ClockIpGpio5 Clock = (1 << 8) | CCM_CCGR1_CG15_Pos // CCGR1, CG15
|
||||
|
||||
ClockIpOcramExsc Clock = (2 << 8) | CCM_CCGR2_CG0_Pos // CCGR2, CG0
|
||||
ClockIpCsi Clock = (2 << 8) | CCM_CCGR2_CG1_Pos // CCGR2, CG1
|
||||
ClockIpIomuxcSnvs Clock = (2 << 8) | CCM_CCGR2_CG2_Pos // CCGR2, CG2
|
||||
ClockIpLpi2c1 Clock = (2 << 8) | CCM_CCGR2_CG3_Pos // CCGR2, CG3
|
||||
ClockIpLpi2c2 Clock = (2 << 8) | CCM_CCGR2_CG4_Pos // CCGR2, CG4
|
||||
ClockIpLpi2c3 Clock = (2 << 8) | CCM_CCGR2_CG5_Pos // CCGR2, CG5
|
||||
ClockIpOcotp Clock = (2 << 8) | CCM_CCGR2_CG6_Pos // CCGR2, CG6
|
||||
ClockIpXbar3 Clock = (2 << 8) | CCM_CCGR2_CG7_Pos // CCGR2, CG7
|
||||
ClockIpIpmux1 Clock = (2 << 8) | CCM_CCGR2_CG8_Pos // CCGR2, CG8
|
||||
ClockIpIpmux2 Clock = (2 << 8) | CCM_CCGR2_CG9_Pos // CCGR2, CG9
|
||||
ClockIpIpmux3 Clock = (2 << 8) | CCM_CCGR2_CG10_Pos // CCGR2, CG10
|
||||
ClockIpXbar1 Clock = (2 << 8) | CCM_CCGR2_CG11_Pos // CCGR2, CG11
|
||||
ClockIpXbar2 Clock = (2 << 8) | CCM_CCGR2_CG12_Pos // CCGR2, CG12
|
||||
ClockIpGpio3 Clock = (2 << 8) | CCM_CCGR2_CG13_Pos // CCGR2, CG13
|
||||
ClockIpLcd Clock = (2 << 8) | CCM_CCGR2_CG14_Pos // CCGR2, CG14
|
||||
ClockIpPxp Clock = (2 << 8) | CCM_CCGR2_CG15_Pos // CCGR2, CG15
|
||||
|
||||
ClockIpFlexio2 Clock = (3 << 8) | CCM_CCGR3_CG0_Pos // CCGR3, CG0
|
||||
ClockIpLpuart5 Clock = (3 << 8) | CCM_CCGR3_CG1_Pos // CCGR3, CG1
|
||||
ClockIpSemc Clock = (3 << 8) | CCM_CCGR3_CG2_Pos // CCGR3, CG2
|
||||
ClockIpLpuart6 Clock = (3 << 8) | CCM_CCGR3_CG3_Pos // CCGR3, CG3
|
||||
ClockIpAoi1 Clock = (3 << 8) | CCM_CCGR3_CG4_Pos // CCGR3, CG4
|
||||
ClockIpLcdPixel Clock = (3 << 8) | CCM_CCGR3_CG5_Pos // CCGR3, CG5
|
||||
ClockIpGpio4 Clock = (3 << 8) | CCM_CCGR3_CG6_Pos // CCGR3, CG6
|
||||
ClockIpEwm0 Clock = (3 << 8) | CCM_CCGR3_CG7_Pos // CCGR3, CG7
|
||||
ClockIpWdog1 Clock = (3 << 8) | CCM_CCGR3_CG8_Pos // CCGR3, CG8
|
||||
ClockIpFlexRam Clock = (3 << 8) | CCM_CCGR3_CG9_Pos // CCGR3, CG9
|
||||
ClockIpAcmp1 Clock = (3 << 8) | CCM_CCGR3_CG10_Pos // CCGR3, CG10
|
||||
ClockIpAcmp2 Clock = (3 << 8) | CCM_CCGR3_CG11_Pos // CCGR3, CG11
|
||||
ClockIpAcmp3 Clock = (3 << 8) | CCM_CCGR3_CG12_Pos // CCGR3, CG12
|
||||
ClockIpAcmp4 Clock = (3 << 8) | CCM_CCGR3_CG13_Pos // CCGR3, CG13
|
||||
ClockIpOcram Clock = (3 << 8) | CCM_CCGR3_CG14_Pos // CCGR3, CG14
|
||||
ClockIpIomuxcSnvsGpr Clock = (3 << 8) | CCM_CCGR3_CG15_Pos // CCGR3, CG15
|
||||
|
||||
ClockIpIomuxc Clock = (4 << 8) | CCM_CCGR4_CG1_Pos // CCGR4, CG1
|
||||
ClockIpIomuxcGpr Clock = (4 << 8) | CCM_CCGR4_CG2_Pos // CCGR4, CG2
|
||||
ClockIpBee Clock = (4 << 8) | CCM_CCGR4_CG3_Pos // CCGR4, CG3
|
||||
ClockIpSimM7 Clock = (4 << 8) | CCM_CCGR4_CG4_Pos // CCGR4, CG4
|
||||
ClockIpTsc Clock = (4 << 8) | CCM_CCGR4_CG5_Pos // CCGR4, CG5
|
||||
ClockIpSimM Clock = (4 << 8) | CCM_CCGR4_CG6_Pos // CCGR4, CG6
|
||||
ClockIpSimEms Clock = (4 << 8) | CCM_CCGR4_CG7_Pos // CCGR4, CG7
|
||||
ClockIpPwm1 Clock = (4 << 8) | CCM_CCGR4_CG8_Pos // CCGR4, CG8
|
||||
ClockIpPwm2 Clock = (4 << 8) | CCM_CCGR4_CG9_Pos // CCGR4, CG9
|
||||
ClockIpPwm3 Clock = (4 << 8) | CCM_CCGR4_CG10_Pos // CCGR4, CG10
|
||||
ClockIpPwm4 Clock = (4 << 8) | CCM_CCGR4_CG11_Pos // CCGR4, CG11
|
||||
ClockIpEnc1 Clock = (4 << 8) | CCM_CCGR4_CG12_Pos // CCGR4, CG12
|
||||
ClockIpEnc2 Clock = (4 << 8) | CCM_CCGR4_CG13_Pos // CCGR4, CG13
|
||||
ClockIpEnc3 Clock = (4 << 8) | CCM_CCGR4_CG14_Pos // CCGR4, CG14
|
||||
ClockIpEnc4 Clock = (4 << 8) | CCM_CCGR4_CG15_Pos // CCGR4, CG15
|
||||
|
||||
ClockIpRom Clock = (5 << 8) | CCM_CCGR5_CG0_Pos // CCGR5, CG0
|
||||
ClockIpFlexio1 Clock = (5 << 8) | CCM_CCGR5_CG1_Pos // CCGR5, CG1
|
||||
ClockIpWdog3 Clock = (5 << 8) | CCM_CCGR5_CG2_Pos // CCGR5, CG2
|
||||
ClockIpDma Clock = (5 << 8) | CCM_CCGR5_CG3_Pos // CCGR5, CG3
|
||||
ClockIpKpp Clock = (5 << 8) | CCM_CCGR5_CG4_Pos // CCGR5, CG4
|
||||
ClockIpWdog2 Clock = (5 << 8) | CCM_CCGR5_CG5_Pos // CCGR5, CG5
|
||||
ClockIpAipsTz4 Clock = (5 << 8) | CCM_CCGR5_CG6_Pos // CCGR5, CG6
|
||||
ClockIpSpdif Clock = (5 << 8) | CCM_CCGR5_CG7_Pos // CCGR5, CG7
|
||||
ClockIpSimMain Clock = (5 << 8) | CCM_CCGR5_CG8_Pos // CCGR5, CG8
|
||||
ClockIpSai1 Clock = (5 << 8) | CCM_CCGR5_CG9_Pos // CCGR5, CG9
|
||||
ClockIpSai2 Clock = (5 << 8) | CCM_CCGR5_CG10_Pos // CCGR5, CG10
|
||||
ClockIpSai3 Clock = (5 << 8) | CCM_CCGR5_CG11_Pos // CCGR5, CG11
|
||||
ClockIpLpuart1 Clock = (5 << 8) | CCM_CCGR5_CG12_Pos // CCGR5, CG12
|
||||
ClockIpLpuart7 Clock = (5 << 8) | CCM_CCGR5_CG13_Pos // CCGR5, CG13
|
||||
ClockIpSnvsHp Clock = (5 << 8) | CCM_CCGR5_CG14_Pos // CCGR5, CG14
|
||||
ClockIpSnvsLp Clock = (5 << 8) | CCM_CCGR5_CG15_Pos // CCGR5, CG15
|
||||
|
||||
ClockIpUsbOh3 Clock = (6 << 8) | CCM_CCGR6_CG0_Pos // CCGR6, CG0
|
||||
ClockIpUsdhc1 Clock = (6 << 8) | CCM_CCGR6_CG1_Pos // CCGR6, CG1
|
||||
ClockIpUsdhc2 Clock = (6 << 8) | CCM_CCGR6_CG2_Pos // CCGR6, CG2
|
||||
ClockIpDcdc Clock = (6 << 8) | CCM_CCGR6_CG3_Pos // CCGR6, CG3
|
||||
ClockIpIpmux4 Clock = (6 << 8) | CCM_CCGR6_CG4_Pos // CCGR6, CG4
|
||||
ClockIpFlexSpi Clock = (6 << 8) | CCM_CCGR6_CG5_Pos // CCGR6, CG5
|
||||
ClockIpTrng Clock = (6 << 8) | CCM_CCGR6_CG6_Pos // CCGR6, CG6
|
||||
ClockIpLpuart8 Clock = (6 << 8) | CCM_CCGR6_CG7_Pos // CCGR6, CG7
|
||||
ClockIpTimer4 Clock = (6 << 8) | CCM_CCGR6_CG8_Pos // CCGR6, CG8
|
||||
ClockIpAipsTz3 Clock = (6 << 8) | CCM_CCGR6_CG9_Pos // CCGR6, CG9
|
||||
ClockIpSimPer Clock = (6 << 8) | CCM_CCGR6_CG10_Pos // CCGR6, CG10
|
||||
ClockIpAnadig Clock = (6 << 8) | CCM_CCGR6_CG11_Pos // CCGR6, CG11
|
||||
ClockIpLpi2c4 Clock = (6 << 8) | CCM_CCGR6_CG12_Pos // CCGR6, CG12
|
||||
ClockIpTimer1 Clock = (6 << 8) | CCM_CCGR6_CG13_Pos // CCGR6, CG13
|
||||
ClockIpTimer2 Clock = (6 << 8) | CCM_CCGR6_CG14_Pos // CCGR6, CG14
|
||||
ClockIpTimer3 Clock = (6 << 8) | CCM_CCGR6_CG15_Pos // CCGR6, CG15
|
||||
|
||||
ClockIpEnet2 Clock = (7 << 8) | CCM_CCGR7_CG0_Pos // CCGR7, CG0
|
||||
ClockIpFlexSpi2 Clock = (7 << 8) | CCM_CCGR7_CG1_Pos // CCGR7, CG1
|
||||
ClockIpAxbsL Clock = (7 << 8) | CCM_CCGR7_CG2_Pos // CCGR7, CG2
|
||||
ClockIpCan3 Clock = (7 << 8) | CCM_CCGR7_CG3_Pos // CCGR7, CG3
|
||||
ClockIpCan3S Clock = (7 << 8) | CCM_CCGR7_CG4_Pos // CCGR7, CG4
|
||||
ClockIpAipsLite Clock = (7 << 8) | CCM_CCGR7_CG5_Pos // CCGR7, CG5
|
||||
ClockIpFlexio3 Clock = (7 << 8) | CCM_CCGR7_CG6_Pos // CCGR7, CG6
|
||||
)
|
||||
|
||||
// PLL name
|
||||
const (
|
||||
ClockPllArm Clock = ((offPllArm & 0xFFF) << 16) | CCM_ANALOG_PLL_ARM_ENABLE_Pos // PLL ARM
|
||||
ClockPllSys Clock = ((offPllSys & 0xFFF) << 16) | CCM_ANALOG_PLL_SYS_ENABLE_Pos // PLL SYS
|
||||
ClockPllUsb1 Clock = ((offPllUsb1 & 0xFFF) << 16) | CCM_ANALOG_PLL_USB1_ENABLE_Pos // PLL USB1
|
||||
ClockPllAudio Clock = ((offPllAudio & 0xFFF) << 16) | CCM_ANALOG_PLL_AUDIO_ENABLE_Pos // PLL Audio
|
||||
ClockPllVideo Clock = ((offPllVideo & 0xFFF) << 16) | CCM_ANALOG_PLL_VIDEO_ENABLE_Pos // PLL Video
|
||||
ClockPllEnet Clock = ((offPllEnet & 0xFFF) << 16) | CCM_ANALOG_PLL_ENET_ENABLE_Pos // PLL Enet0
|
||||
ClockPllEnet2 Clock = ((offPllEnet & 0xFFF) << 16) | CCM_ANALOG_PLL_ENET_ENET2_REF_EN_Pos // PLL Enet1
|
||||
ClockPllEnet25M Clock = ((offPllEnet & 0xFFF) << 16) | CCM_ANALOG_PLL_ENET_ENET_25M_REF_EN_Pos // PLL Enet2
|
||||
ClockPllUsb2 Clock = ((offPllUsb2 & 0xFFF) << 16) | CCM_ANALOG_PLL_USB2_ENABLE_Pos // PLL USB2
|
||||
)
|
||||
|
||||
// PLL PFD name
|
||||
const (
|
||||
ClockPfd0 Clock = 0 // PLL PFD0
|
||||
ClockPfd1 Clock = 1 // PLL PFD1
|
||||
ClockPfd2 Clock = 2 // PLL PFD2
|
||||
ClockPfd3 Clock = 3 // PLL PFD3
|
||||
)
|
||||
|
||||
// Named clock muxes of integrated peripherals
|
||||
const (
|
||||
MuxIpPll3Sw Clock = (offCCSR & 0xFF) | (CCM_CCSR_PLL3_SW_CLK_SEL_Pos << 8) | (((CCM_CCSR_PLL3_SW_CLK_SEL_Msk >> CCM_CCSR_PLL3_SW_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // pll3_sw_clk mux name
|
||||
MuxIpPeriph Clock = (offCBCDR & 0xFF) | (CCM_CBCDR_PERIPH_CLK_SEL_Pos << 8) | (((CCM_CBCDR_PERIPH_CLK_SEL_Msk >> CCM_CBCDR_PERIPH_CLK_SEL_Pos) & 0x1FFF) << 13) | (CCM_CDHIPR_PERIPH_CLK_SEL_BUSY_Pos << 26) // periph mux name
|
||||
MuxIpSemcAlt Clock = (offCBCDR & 0xFF) | (CCM_CBCDR_SEMC_ALT_CLK_SEL_Pos << 8) | (((CCM_CBCDR_SEMC_ALT_CLK_SEL_Msk >> CCM_CBCDR_SEMC_ALT_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // semc mux name
|
||||
MuxIpSemc Clock = (offCBCDR & 0xFF) | (CCM_CBCDR_SEMC_CLK_SEL_Pos << 8) | (((CCM_CBCDR_SEMC_CLK_SEL_Msk >> CCM_CBCDR_SEMC_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // semc mux name
|
||||
MuxIpPrePeriph Clock = (offCBCMR & 0xFF) | (CCM_CBCMR_PRE_PERIPH_CLK_SEL_Pos << 8) | (((CCM_CBCMR_PRE_PERIPH_CLK_SEL_Msk >> CCM_CBCMR_PRE_PERIPH_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // pre-periph mux name
|
||||
MuxIpTrace Clock = (offCBCMR & 0xFF) | (CCM_CBCMR_TRACE_CLK_SEL_Pos << 8) | (((CCM_CBCMR_TRACE_CLK_SEL_Msk >> CCM_CBCMR_TRACE_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // trace mux name
|
||||
MuxIpPeriphClk2 Clock = (offCBCMR & 0xFF) | (CCM_CBCMR_PERIPH_CLK2_SEL_Pos << 8) | (((CCM_CBCMR_PERIPH_CLK2_SEL_Msk >> CCM_CBCMR_PERIPH_CLK2_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // periph clock2 mux name
|
||||
MuxIpFlexSpi2 Clock = (offCBCMR & 0xFF) | (CCM_CBCMR_FLEXSPI2_CLK_SEL_Pos << 8) | (((CCM_CBCMR_FLEXSPI2_CLK_SEL_Msk >> CCM_CBCMR_FLEXSPI2_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // flexspi2 mux name
|
||||
MuxIpLpspi Clock = (offCBCMR & 0xFF) | (CCM_CBCMR_LPSPI_CLK_SEL_Pos << 8) | (((CCM_CBCMR_LPSPI_CLK_SEL_Msk >> CCM_CBCMR_LPSPI_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // lpspi mux name
|
||||
MuxIpFlexSpi Clock = (offCSCMR1 & 0xFF) | (CCM_CSCMR1_FLEXSPI_CLK_SEL_Pos << 8) | (((CCM_CSCMR1_FLEXSPI_CLK_SEL_Msk >> CCM_CSCMR1_FLEXSPI_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // flexspi mux name
|
||||
MuxIpUsdhc2 Clock = (offCSCMR1 & 0xFF) | (CCM_CSCMR1_USDHC2_CLK_SEL_Pos << 8) | (((CCM_CSCMR1_USDHC2_CLK_SEL_Msk >> CCM_CSCMR1_USDHC2_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // usdhc2 mux name
|
||||
MuxIpUsdhc1 Clock = (offCSCMR1 & 0xFF) | (CCM_CSCMR1_USDHC1_CLK_SEL_Pos << 8) | (((CCM_CSCMR1_USDHC1_CLK_SEL_Msk >> CCM_CSCMR1_USDHC1_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // usdhc1 mux name
|
||||
MuxIpSai3 Clock = (offCSCMR1 & 0xFF) | (CCM_CSCMR1_SAI3_CLK_SEL_Pos << 8) | (((CCM_CSCMR1_SAI3_CLK_SEL_Msk >> CCM_CSCMR1_SAI3_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // sai3 mux name
|
||||
MuxIpSai2 Clock = (offCSCMR1 & 0xFF) | (CCM_CSCMR1_SAI2_CLK_SEL_Pos << 8) | (((CCM_CSCMR1_SAI2_CLK_SEL_Msk >> CCM_CSCMR1_SAI2_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // sai2 mux name
|
||||
MuxIpSai1 Clock = (offCSCMR1 & 0xFF) | (CCM_CSCMR1_SAI1_CLK_SEL_Pos << 8) | (((CCM_CSCMR1_SAI1_CLK_SEL_Msk >> CCM_CSCMR1_SAI1_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // sai1 mux name
|
||||
MuxIpPerclk Clock = (offCSCMR1 & 0xFF) | (CCM_CSCMR1_PERCLK_CLK_SEL_Pos << 8) | (((CCM_CSCMR1_PERCLK_CLK_SEL_Msk >> CCM_CSCMR1_PERCLK_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // perclk mux name
|
||||
MuxIpFlexio2 Clock = (offCSCMR2 & 0xFF) | (CCM_CSCMR2_FLEXIO2_CLK_SEL_Pos << 8) | (((CCM_CSCMR2_FLEXIO2_CLK_SEL_Msk >> CCM_CSCMR2_FLEXIO2_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // flexio2 mux name
|
||||
MuxIpCan Clock = (offCSCMR2 & 0xFF) | (CCM_CSCMR2_CAN_CLK_SEL_Pos << 8) | (((CCM_CSCMR2_CAN_CLK_SEL_Msk >> CCM_CSCMR2_CAN_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // can mux name
|
||||
MuxIpUart Clock = (offCSCDR1 & 0xFF) | (CCM_CSCDR1_UART_CLK_SEL_Pos << 8) | (((CCM_CSCDR1_UART_CLK_SEL_Msk >> CCM_CSCDR1_UART_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // uart mux name
|
||||
MuxIpSpdif Clock = (offCDCDR & 0xFF) | (CCM_CDCDR_SPDIF0_CLK_SEL_Pos << 8) | (((CCM_CDCDR_SPDIF0_CLK_SEL_Msk >> CCM_CDCDR_SPDIF0_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // spdif mux name
|
||||
MuxIpFlexio1 Clock = (offCDCDR & 0xFF) | (CCM_CDCDR_FLEXIO1_CLK_SEL_Pos << 8) | (((CCM_CDCDR_FLEXIO1_CLK_SEL_Msk >> CCM_CDCDR_FLEXIO1_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // flexio1 mux name
|
||||
MuxIpLpi2c Clock = (offCSCDR2 & 0xFF) | (CCM_CSCDR2_LPI2C_CLK_SEL_Pos << 8) | (((CCM_CSCDR2_LPI2C_CLK_SEL_Msk >> CCM_CSCDR2_LPI2C_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // lpi2c mux name
|
||||
MuxIpLcdifPre Clock = (offCSCDR2 & 0xFF) | (CCM_CSCDR2_LCDIF_PRE_CLK_SEL_Pos << 8) | (((CCM_CSCDR2_LCDIF_PRE_CLK_SEL_Msk >> CCM_CSCDR2_LCDIF_PRE_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // lcdif pre mux name
|
||||
MuxIpCsi Clock = (offCSCDR3 & 0xFF) | (CCM_CSCDR3_CSI_CLK_SEL_Pos << 8) | (((CCM_CSCDR3_CSI_CLK_SEL_Msk >> CCM_CSCDR3_CSI_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // csi mux name
|
||||
)
|
||||
|
||||
// Named hardware clock divisors of integrated peripherals
|
||||
const (
|
||||
DivIpArm Clock = (offCACRR & 0xFF) | (CCM_CACRR_ARM_PODF_Pos << 8) | (((CCM_CACRR_ARM_PODF_Msk >> CCM_CACRR_ARM_PODF_Pos) & 0x1FFF) << 13) | (CCM_CDHIPR_ARM_PODF_BUSY_Pos << 26) // core div name
|
||||
DivIpPeriphClk2 Clock = (offCBCDR & 0xFF) | (CCM_CBCDR_PERIPH_CLK2_PODF_Pos << 8) | (((CCM_CBCDR_PERIPH_CLK2_PODF_Msk >> CCM_CBCDR_PERIPH_CLK2_PODF_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // periph clock2 div name
|
||||
DivIpSemc Clock = (offCBCDR & 0xFF) | (CCM_CBCDR_SEMC_PODF_Pos << 8) | (((CCM_CBCDR_SEMC_PODF_Msk >> CCM_CBCDR_SEMC_PODF_Pos) & 0x1FFF) << 13) | (CCM_CDHIPR_SEMC_PODF_BUSY_Pos << 26) // semc div name
|
||||
DivIpAhb Clock = (offCBCDR & 0xFF) | (CCM_CBCDR_AHB_PODF_Pos << 8) | (((CCM_CBCDR_AHB_PODF_Msk >> CCM_CBCDR_AHB_PODF_Pos) & 0x1FFF) << 13) | (CCM_CDHIPR_AHB_PODF_BUSY_Pos << 26) // ahb div name
|
||||
DivIpIpg Clock = (offCBCDR & 0xFF) | (CCM_CBCDR_IPG_PODF_Pos << 8) | (((CCM_CBCDR_IPG_PODF_Msk >> CCM_CBCDR_IPG_PODF_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // ipg div name
|
||||
DivIpFlexSpi2 Clock = (offCBCMR & 0xFF) | (CCM_CBCMR_FLEXSPI2_PODF_Pos << 8) | (((CCM_CBCMR_FLEXSPI2_PODF_Msk >> CCM_CBCMR_FLEXSPI2_PODF_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // flexspi2 div name
|
||||
DivIpLpspi Clock = (offCBCMR & 0xFF) | (CCM_CBCMR_LPSPI_PODF_Pos << 8) | (((CCM_CBCMR_LPSPI_PODF_Msk >> CCM_CBCMR_LPSPI_PODF_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // lpspi div name
|
||||
DivIpLcdif Clock = (offCBCMR & 0xFF) | (CCM_CBCMR_LCDIF_PODF_Pos << 8) | (((CCM_CBCMR_LCDIF_PODF_Msk >> CCM_CBCMR_LCDIF_PODF_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // lcdif div name
|
||||
DivIpFlexSpi Clock = (offCSCMR1 & 0xFF) | (CCM_CSCMR1_FLEXSPI_PODF_Pos << 8) | (((CCM_CSCMR1_FLEXSPI_PODF_Msk >> CCM_CSCMR1_FLEXSPI_PODF_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // flexspi div name
|
||||
DivIpPerclk Clock = (offCSCMR1 & 0xFF) | (CCM_CSCMR1_PERCLK_PODF_Pos << 8) | (((CCM_CSCMR1_PERCLK_PODF_Msk >> CCM_CSCMR1_PERCLK_PODF_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // perclk div name
|
||||
DivIpCan Clock = (offCSCMR2 & 0xFF) | (CCM_CSCMR2_CAN_CLK_PODF_Pos << 8) | (((CCM_CSCMR2_CAN_CLK_PODF_Msk >> CCM_CSCMR2_CAN_CLK_PODF_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // can div name
|
||||
DivIpTrace Clock = (offCSCDR1 & 0xFF) | (CCM_CSCDR1_TRACE_PODF_Pos << 8) | (((CCM_CSCDR1_TRACE_PODF_Msk >> CCM_CSCDR1_TRACE_PODF_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // trace div name
|
||||
DivIpUsdhc2 Clock = (offCSCDR1 & 0xFF) | (CCM_CSCDR1_USDHC2_PODF_Pos << 8) | (((CCM_CSCDR1_USDHC2_PODF_Msk >> CCM_CSCDR1_USDHC2_PODF_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // usdhc2 div name
|
||||
DivIpUsdhc1 Clock = (offCSCDR1 & 0xFF) | (CCM_CSCDR1_USDHC1_PODF_Pos << 8) | (((CCM_CSCDR1_USDHC1_PODF_Msk >> CCM_CSCDR1_USDHC1_PODF_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // usdhc1 div name
|
||||
DivIpUart Clock = (offCSCDR1 & 0xFF) | (CCM_CSCDR1_UART_CLK_PODF_Pos << 8) | (((CCM_CSCDR1_UART_CLK_PODF_Msk >> CCM_CSCDR1_UART_CLK_PODF_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // uart div name
|
||||
DivIpFlexio2 Clock = (offCS1CDR & 0xFF) | (CCM_CS1CDR_FLEXIO2_CLK_PODF_Pos << 8) | (((CCM_CS1CDR_FLEXIO2_CLK_PODF_Msk >> CCM_CS1CDR_FLEXIO2_CLK_PODF_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // flexio2 pre div name
|
||||
DivIpSai3Pre Clock = (offCS1CDR & 0xFF) | (CCM_CS1CDR_SAI3_CLK_PRED_Pos << 8) | (((CCM_CS1CDR_SAI3_CLK_PRED_Msk >> CCM_CS1CDR_SAI3_CLK_PRED_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // sai3 pre div name
|
||||
DivIpSai3 Clock = (offCS1CDR & 0xFF) | (CCM_CS1CDR_SAI3_CLK_PODF_Pos << 8) | (((CCM_CS1CDR_SAI3_CLK_PODF_Msk >> CCM_CS1CDR_SAI3_CLK_PODF_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // sai3 div name
|
||||
DivIpFlexio2Pre Clock = (offCS1CDR & 0xFF) | (CCM_CS1CDR_FLEXIO2_CLK_PRED_Pos << 8) | (((CCM_CS1CDR_FLEXIO2_CLK_PRED_Msk >> CCM_CS1CDR_FLEXIO2_CLK_PRED_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // sai3 pre div name
|
||||
DivIpSai1Pre Clock = (offCS1CDR & 0xFF) | (CCM_CS1CDR_SAI1_CLK_PRED_Pos << 8) | (((CCM_CS1CDR_SAI1_CLK_PRED_Msk >> CCM_CS1CDR_SAI1_CLK_PRED_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // sai1 pre div name
|
||||
DivIpSai1 Clock = (offCS1CDR & 0xFF) | (CCM_CS1CDR_SAI1_CLK_PODF_Pos << 8) | (((CCM_CS1CDR_SAI1_CLK_PODF_Msk >> CCM_CS1CDR_SAI1_CLK_PODF_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // sai1 div name
|
||||
DivIpSai2Pre Clock = (offCS2CDR & 0xFF) | (CCM_CS2CDR_SAI2_CLK_PRED_Pos << 8) | (((CCM_CS2CDR_SAI2_CLK_PRED_Msk >> CCM_CS2CDR_SAI2_CLK_PRED_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // sai2 pre div name
|
||||
DivIpSai2 Clock = (offCS2CDR & 0xFF) | (CCM_CS2CDR_SAI2_CLK_PODF_Pos << 8) | (((CCM_CS2CDR_SAI2_CLK_PODF_Msk >> CCM_CS2CDR_SAI2_CLK_PODF_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // sai2 div name
|
||||
DivIpSpdif0Pre Clock = (offCDCDR & 0xFF) | (CCM_CDCDR_SPDIF0_CLK_PRED_Pos << 8) | (((CCM_CDCDR_SPDIF0_CLK_PRED_Msk >> CCM_CDCDR_SPDIF0_CLK_PRED_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // spdif pre div name
|
||||
DivIpSpdif0 Clock = (offCDCDR & 0xFF) | (CCM_CDCDR_SPDIF0_CLK_PODF_Pos << 8) | (((CCM_CDCDR_SPDIF0_CLK_PODF_Msk >> CCM_CDCDR_SPDIF0_CLK_PODF_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // spdif div name
|
||||
DivIpFlexio1Pre Clock = (offCDCDR & 0xFF) | (CCM_CDCDR_FLEXIO1_CLK_PRED_Pos << 8) | (((CCM_CDCDR_FLEXIO1_CLK_PRED_Msk >> CCM_CDCDR_FLEXIO1_CLK_PRED_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // flexio1 pre div name
|
||||
DivIpFlexio1 Clock = (offCDCDR & 0xFF) | (CCM_CDCDR_FLEXIO1_CLK_PODF_Pos << 8) | (((CCM_CDCDR_FLEXIO1_CLK_PODF_Msk >> CCM_CDCDR_FLEXIO1_CLK_PODF_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // flexio1 div name
|
||||
DivIpLpi2c Clock = (offCSCDR2 & 0xFF) | (CCM_CSCDR2_LPI2C_CLK_PODF_Pos << 8) | (((CCM_CSCDR2_LPI2C_CLK_PODF_Msk >> CCM_CSCDR2_LPI2C_CLK_PODF_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // lpi2c div name
|
||||
DivIpLcdifPre Clock = (offCSCDR2 & 0xFF) | (CCM_CSCDR2_LCDIF_PRED_Pos << 8) | (((CCM_CSCDR2_LCDIF_PRED_Msk >> CCM_CSCDR2_LCDIF_PRED_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // lcdif pre div name
|
||||
DivIpCsi Clock = (offCSCDR3 & 0xFF) | (CCM_CSCDR3_CSI_PODF_Pos << 8) | (((CCM_CSCDR3_CSI_PODF_Msk >> CCM_CSCDR3_CSI_PODF_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // csi div name
|
||||
)
|
||||
|
||||
// Selected clock offsets
|
||||
const (
|
||||
offCCSR = 0x0C
|
||||
offCBCDR = 0x14
|
||||
offCBCMR = 0x18
|
||||
offCSCMR1 = 0x1C
|
||||
offCSCMR2 = 0x20
|
||||
offCSCDR1 = 0x24
|
||||
offCDCDR = 0x30
|
||||
offCSCDR2 = 0x38
|
||||
offCSCDR3 = 0x3C
|
||||
offCACRR = 0x10
|
||||
offCS1CDR = 0x28
|
||||
offCS2CDR = 0x2C
|
||||
|
||||
offPllArm = 0x00
|
||||
offPllSys = 0x30
|
||||
offPllUsb1 = 0x10
|
||||
offPllAudio = 0x70
|
||||
offPllVideo = 0xA0
|
||||
offPllEnet = 0xE0
|
||||
offPllUsb2 = 0x20
|
||||
|
||||
noBusyWait = 0x20
|
||||
)
|
||||
|
||||
// analog PLL definition
|
||||
const (
|
||||
pllBypassPos = 16
|
||||
pllBypassClkSrcMsk = 0xC000
|
||||
pllBypassClkSrcPos = 14
|
||||
)
|
||||
|
||||
// PLL clock source, bypass cloco source also
|
||||
const (
|
||||
pllSrc24M = 0 // Pll clock source 24M
|
||||
pllSrcClkPN = 1 // Pll clock source CLK1_P and CLK1_N
|
||||
)
|
||||
|
||||
const (
|
||||
clockNotNeeded uint32 = 0 // Clock is off during all modes
|
||||
clockNeededRun uint32 = 1 // Clock is on in run mode, but off in WAIT and STOP modes
|
||||
clockNeededRunWait uint32 = 3 // Clock is on during all modes, except STOP mode
|
||||
)
|
||||
|
||||
// getGate returns the CCM clock gating register for the receiver clk.
|
||||
func (clk Clock) getGate() *volatile.Register32 {
|
||||
switch clk >> 8 {
|
||||
case 0:
|
||||
return &CCM.CCGR0
|
||||
case 1:
|
||||
return &CCM.CCGR1
|
||||
case 2:
|
||||
return &CCM.CCGR2
|
||||
case 3:
|
||||
return &CCM.CCGR3
|
||||
case 4:
|
||||
return &CCM.CCGR4
|
||||
case 5:
|
||||
return &CCM.CCGR5
|
||||
case 6:
|
||||
return &CCM.CCGR6
|
||||
case 7:
|
||||
return &CCM.CCGR7
|
||||
default:
|
||||
panic("nxp: invalid clock")
|
||||
}
|
||||
}
|
||||
|
||||
// setGate enables or disables the receiver clk using its gating register.
|
||||
func (clk Clock) setGate(value uint32) {
|
||||
reg := clk.getGate()
|
||||
shift := clk & 0x1F
|
||||
reg.Set((reg.Get() & ^(3 << shift)) | (value << shift))
|
||||
}
|
||||
|
||||
func (clk Clock) setCcm(value uint32) {
|
||||
const ccmBase = 0x400fc000
|
||||
reg := (*volatile.Register32)(unsafe.Pointer(uintptr(ccmBase + (uint32(clk) & 0xFF))))
|
||||
msk := ((uint32(clk) >> 13) & 0x1FFF) << ((uint32(clk) >> 8) & 0x1F)
|
||||
pos := (uint32(clk) >> 8) & 0x1F
|
||||
bsy := (uint32(clk) >> 26) & 0x3F
|
||||
reg.Set((reg.Get() & ^uint32(msk)) | ((value << pos) & msk))
|
||||
if bsy < noBusyWait {
|
||||
for CCM.CDHIPR.HasBits(1 << bsy) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func setSysPfd(value ...uint32) {
|
||||
for i, val := range value {
|
||||
pfd528 := CCM_ANALOG.PFD_528.Get() &
|
||||
^((CCM_ANALOG_PFD_528_PFD0_CLKGATE_Msk | CCM_ANALOG_PFD_528_PFD0_FRAC_Msk) << (8 * uint32(i)))
|
||||
frac := (val << CCM_ANALOG_PFD_528_PFD0_FRAC_Pos) & CCM_ANALOG_PFD_528_PFD0_FRAC_Msk
|
||||
// disable the clock output first
|
||||
CCM_ANALOG.PFD_528.Set(pfd528 | (CCM_ANALOG_PFD_528_PFD0_CLKGATE_Msk << (8 * uint32(i))))
|
||||
// set the new value and enable output
|
||||
CCM_ANALOG.PFD_528.Set(pfd528 | (frac << (8 * uint32(i))))
|
||||
}
|
||||
}
|
||||
|
||||
func setUsb1Pfd(value ...uint32) {
|
||||
for i, val := range value {
|
||||
pfd480 := CCM_ANALOG.PFD_480.Get() &
|
||||
^((CCM_ANALOG_PFD_480_PFD0_CLKGATE_Msk | CCM_ANALOG_PFD_480_PFD0_FRAC_Msk) << (8 * uint32(i)))
|
||||
frac := (val << CCM_ANALOG_PFD_480_PFD0_FRAC_Pos) & CCM_ANALOG_PFD_480_PFD0_FRAC_Msk
|
||||
// disable the clock output first
|
||||
CCM_ANALOG.PFD_480.Set(pfd480 | (CCM_ANALOG_PFD_480_PFD0_CLKGATE_Msk << (8 * uint32(i))))
|
||||
// set the new value and enable output
|
||||
CCM_ANALOG.PFD_480.Set(pfd480 | (frac << (8 * uint32(i))))
|
||||
}
|
||||
}
|
||||
|
||||
// PLL configuration for ARM
|
||||
type ClockConfigArmPll struct {
|
||||
LoopDivider uint32 // PLL loop divider. Valid range for divider value: 54-108. Fout=Fin*LoopDivider/2.
|
||||
Src uint8 // Pll clock source, reference _clock_pll_clk_src
|
||||
}
|
||||
|
||||
func (cfg ClockConfigArmPll) Configure() {
|
||||
|
||||
// bypass PLL first
|
||||
src := (uint32(cfg.Src) << CCM_ANALOG_PLL_ARM_BYPASS_CLK_SRC_Pos) & CCM_ANALOG_PLL_ARM_BYPASS_CLK_SRC_Msk
|
||||
CCM_ANALOG.PLL_ARM.Set(
|
||||
(CCM_ANALOG.PLL_ARM.Get() & ^uint32(CCM_ANALOG_PLL_ARM_BYPASS_CLK_SRC_Msk)) |
|
||||
CCM_ANALOG_PLL_ARM_BYPASS_Msk | src)
|
||||
|
||||
sel := (cfg.LoopDivider << CCM_ANALOG_PLL_ARM_DIV_SELECT_Pos) & CCM_ANALOG_PLL_ARM_DIV_SELECT_Msk
|
||||
CCM_ANALOG.PLL_ARM.Set(
|
||||
(CCM_ANALOG.PLL_ARM.Get() & ^uint32(CCM_ANALOG_PLL_ARM_DIV_SELECT_Msk|CCM_ANALOG_PLL_ARM_POWERDOWN_Msk)) |
|
||||
CCM_ANALOG_PLL_ARM_ENABLE_Msk | sel)
|
||||
|
||||
for !CCM_ANALOG.PLL_ARM.HasBits(CCM_ANALOG_PLL_ARM_LOCK_Msk) {
|
||||
}
|
||||
|
||||
// disable bypass
|
||||
CCM_ANALOG.PLL_ARM.ClearBits(CCM_ANALOG_PLL_ARM_BYPASS_Msk)
|
||||
}
|
||||
|
||||
// PLL configuration for System
|
||||
type ClockConfigSysPll struct {
|
||||
LoopDivider uint8 // PLL loop divider. Intended to be 1 (528M): 0 - Fout=Fref*20, 1 - Fout=Fref*22
|
||||
Numerator uint32 // 30 bit Numerator of fractional loop divider.
|
||||
Denominator uint32 // 30 bit Denominator of fractional loop divider
|
||||
Src uint8 // Pll clock source, reference _clock_pll_clk_src
|
||||
SsStop uint16 // Stop value to get frequency change.
|
||||
SsEnable uint8 // Enable spread spectrum modulation
|
||||
SsStep uint16 // Step value to get frequency change step.
|
||||
}
|
||||
|
||||
func (cfg ClockConfigSysPll) Configure(pfd ...uint32) {
|
||||
|
||||
// bypass PLL first
|
||||
src := (uint32(cfg.Src) << CCM_ANALOG_PLL_SYS_BYPASS_CLK_SRC_Pos) & CCM_ANALOG_PLL_SYS_BYPASS_CLK_SRC_Msk
|
||||
CCM_ANALOG.PLL_SYS.Set(
|
||||
(CCM_ANALOG.PLL_SYS.Get() & ^uint32(CCM_ANALOG_PLL_SYS_BYPASS_CLK_SRC_Msk)) |
|
||||
CCM_ANALOG_PLL_SYS_BYPASS_Msk | src)
|
||||
|
||||
sel := (uint32(cfg.LoopDivider) << CCM_ANALOG_PLL_SYS_DIV_SELECT_Pos) & CCM_ANALOG_PLL_SYS_DIV_SELECT_Msk
|
||||
CCM_ANALOG.PLL_SYS.Set(
|
||||
(CCM_ANALOG.PLL_SYS.Get() & ^uint32(CCM_ANALOG_PLL_SYS_DIV_SELECT_Msk|CCM_ANALOG_PLL_SYS_POWERDOWN_Msk)) |
|
||||
CCM_ANALOG_PLL_SYS_ENABLE_Msk | sel)
|
||||
|
||||
// initialize the fractional mode
|
||||
CCM_ANALOG.PLL_SYS_NUM.Set((cfg.Numerator << CCM_ANALOG_PLL_SYS_NUM_A_Pos) & CCM_ANALOG_PLL_SYS_NUM_A_Msk)
|
||||
CCM_ANALOG.PLL_SYS_DENOM.Set((cfg.Denominator << CCM_ANALOG_PLL_SYS_DENOM_B_Pos) & CCM_ANALOG_PLL_SYS_DENOM_B_Msk)
|
||||
|
||||
// initialize the spread spectrum mode
|
||||
inc := (uint32(cfg.SsStep) << CCM_ANALOG_PLL_SYS_SS_STEP_Pos) & CCM_ANALOG_PLL_SYS_SS_STEP_Msk
|
||||
enb := (uint32(cfg.SsEnable) << CCM_ANALOG_PLL_SYS_SS_ENABLE_Pos) & CCM_ANALOG_PLL_SYS_SS_ENABLE_Msk
|
||||
stp := (uint32(cfg.SsStop) << CCM_ANALOG_PLL_SYS_SS_STOP_Pos) & CCM_ANALOG_PLL_SYS_SS_STOP_Msk
|
||||
CCM_ANALOG.PLL_SYS_SS.Set(inc | enb | stp)
|
||||
|
||||
for !CCM_ANALOG.PLL_SYS.HasBits(CCM_ANALOG_PLL_SYS_LOCK_Msk) {
|
||||
}
|
||||
|
||||
// disable bypass
|
||||
CCM_ANALOG.PLL_SYS.ClearBits(CCM_ANALOG_PLL_SYS_BYPASS_Msk)
|
||||
|
||||
// update PFDs after update
|
||||
setSysPfd(pfd...)
|
||||
}
|
||||
|
||||
// PLL configuration for USB
|
||||
type ClockConfigUsbPll struct {
|
||||
Instance uint8 // USB PLL number (1 or 2)
|
||||
LoopDivider uint8 // PLL loop divider: 0 - Fout=Fref*20, 1 - Fout=Fref*22
|
||||
Src uint8 // Pll clock source, reference _clock_pll_clk_src
|
||||
}
|
||||
|
||||
func (cfg ClockConfigUsbPll) Configure(pfd ...uint32) {
|
||||
|
||||
switch cfg.Instance {
|
||||
case 1:
|
||||
|
||||
// bypass PLL first
|
||||
src := (uint32(cfg.Src) << CCM_ANALOG_PLL_USB1_BYPASS_CLK_SRC_Pos) & CCM_ANALOG_PLL_USB1_BYPASS_CLK_SRC_Msk
|
||||
CCM_ANALOG.PLL_USB1.Set(
|
||||
(CCM_ANALOG.PLL_USB1.Get() & ^uint32(CCM_ANALOG_PLL_USB1_BYPASS_CLK_SRC_Msk)) |
|
||||
CCM_ANALOG_PLL_USB1_BYPASS_Msk | src)
|
||||
|
||||
sel := uint32((cfg.LoopDivider << CCM_ANALOG_PLL_USB1_DIV_SELECT_Pos) & CCM_ANALOG_PLL_USB1_DIV_SELECT_Msk)
|
||||
CCM_ANALOG.PLL_USB1_SET.Set(
|
||||
(CCM_ANALOG.PLL_USB1.Get() & ^uint32(CCM_ANALOG_PLL_USB1_DIV_SELECT_Msk)) |
|
||||
CCM_ANALOG_PLL_USB1_ENABLE_Msk | CCM_ANALOG_PLL_USB1_POWER_Msk |
|
||||
CCM_ANALOG_PLL_USB1_EN_USB_CLKS_Msk | sel)
|
||||
|
||||
for !CCM_ANALOG.PLL_USB1.HasBits(CCM_ANALOG_PLL_USB1_LOCK_Msk) {
|
||||
}
|
||||
|
||||
// disable bypass
|
||||
CCM_ANALOG.PLL_USB1_CLR.Set(CCM_ANALOG_PLL_USB1_BYPASS_Msk)
|
||||
|
||||
// update PFDs after update
|
||||
setUsb1Pfd(pfd...)
|
||||
|
||||
case 2:
|
||||
// bypass PLL first
|
||||
src := (uint32(cfg.Src) << CCM_ANALOG_PLL_USB2_BYPASS_CLK_SRC_Pos) & CCM_ANALOG_PLL_USB2_BYPASS_CLK_SRC_Msk
|
||||
CCM_ANALOG.PLL_USB2.Set(
|
||||
(CCM_ANALOG.PLL_USB2.Get() & ^uint32(CCM_ANALOG_PLL_USB2_BYPASS_CLK_SRC_Msk)) |
|
||||
CCM_ANALOG_PLL_USB2_BYPASS_Msk | src)
|
||||
|
||||
sel := uint32((cfg.LoopDivider << CCM_ANALOG_PLL_USB2_DIV_SELECT_Pos) & CCM_ANALOG_PLL_USB2_DIV_SELECT_Msk)
|
||||
CCM_ANALOG.PLL_USB2.Set(
|
||||
(CCM_ANALOG.PLL_USB2.Get() & ^uint32(CCM_ANALOG_PLL_USB2_DIV_SELECT_Msk)) |
|
||||
CCM_ANALOG_PLL_USB2_ENABLE_Msk | CCM_ANALOG_PLL_USB2_POWER_Msk |
|
||||
CCM_ANALOG_PLL_USB2_EN_USB_CLKS_Msk | sel)
|
||||
|
||||
for !CCM_ANALOG.PLL_USB2.HasBits(CCM_ANALOG_PLL_USB2_LOCK_Msk) {
|
||||
}
|
||||
|
||||
// disable bypass
|
||||
CCM_ANALOG.PLL_USB2.ClearBits(CCM_ANALOG_PLL_USB2_BYPASS_Msk)
|
||||
|
||||
default:
|
||||
panic("nxp: invalid USB PLL")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// Hand created file. DO NOT DELETE.
|
||||
// Hardfault aliases for definitions that have inconsistent naming (which are
|
||||
// auto-generated by gen-device-svd.go) among devices in package nxp.
|
||||
|
||||
// +build nxp,mimxrt1062
|
||||
|
||||
package nxp
|
||||
|
||||
const (
|
||||
HardFault_CFSR_IACCVIOL = SCB_CFSR_IACCVIOL
|
||||
HardFault_CFSR_DACCVIOL = SCB_CFSR_DACCVIOL
|
||||
HardFault_CFSR_MUNSTKERR = SCB_CFSR_MUNSTKERR
|
||||
HardFault_CFSR_MSTKERR = SCB_CFSR_MSTKERR
|
||||
HardFault_CFSR_MLSPERR = SCB_CFSR_MLSPERR
|
||||
HardFault_CFSR_IBUSERR = SCB_CFSR_IBUSERR
|
||||
HardFault_CFSR_PRECISERR = SCB_CFSR_PRECISERR
|
||||
HardFault_CFSR_IMPRECISERR = SCB_CFSR_IMPRECISERR
|
||||
HardFault_CFSR_UNSTKERR = SCB_CFSR_UNSTKERR
|
||||
HardFault_CFSR_STKERR = SCB_CFSR_STKERR
|
||||
HardFault_CFSR_LSPERR = SCB_CFSR_LSPERR
|
||||
HardFault_CFSR_UNDEFINSTR = SCB_CFSR_UNDEFINSTR
|
||||
HardFault_CFSR_INVSTATE = SCB_CFSR_INVSTATE
|
||||
HardFault_CFSR_INVPC = SCB_CFSR_INVPC
|
||||
HardFault_CFSR_NOCP = SCB_CFSR_NOCP
|
||||
HardFault_CFSR_UNALIGNED = SCB_CFSR_UNALIGNED
|
||||
HardFault_CFSR_DIVBYZERO = SCB_CFSR_DIVBYZERO
|
||||
HardFault_CFSR_MMARVALID = SCB_CFSR_MMARVALID
|
||||
HardFault_CFSR_BFARVALID = SCB_CFSR_BFARVALID
|
||||
)
|
||||
@@ -0,0 +1,278 @@
|
||||
// Hand created file. DO NOT DELETE.
|
||||
// Type definitions, fields, and constants associated with the MPU peripheral
|
||||
// of the NXP MIMXRT1062.
|
||||
|
||||
// +build nxp,mimxrt1062
|
||||
|
||||
package nxp
|
||||
|
||||
import (
|
||||
"device/arm"
|
||||
"runtime/volatile"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type MPU_Type struct {
|
||||
TYPE volatile.Register32 // 0x000 (R/ ) - MPU Type Register
|
||||
CTRL volatile.Register32 // 0x004 (R/W) - MPU Control Register
|
||||
RNR volatile.Register32 // 0x008 (R/W) - MPU Region RNRber Register
|
||||
RBAR volatile.Register32 // 0x00C (R/W) - MPU Region Base Address Register
|
||||
RASR volatile.Register32 // 0x010 (R/W) - MPU Region Attribute and Size Register
|
||||
RBAR_A1 volatile.Register32 // 0x014 (R/W) - MPU Alias 1 Region Base Address Register
|
||||
RASR_A1 volatile.Register32 // 0x018 (R/W) - MPU Alias 1 Region Attribute and Size Register
|
||||
RBAR_A2 volatile.Register32 // 0x01C (R/W) - MPU Alias 2 Region Base Address Register
|
||||
RASR_A2 volatile.Register32 // 0x020 (R/W) - MPU Alias 2 Region Attribute and Size Register
|
||||
RBAR_A3 volatile.Register32 // 0x024 (R/W) - MPU Alias 3 Region Base Address Register
|
||||
RASR_A3 volatile.Register32 // 0x028 (R/W) - MPU Alias 3 Region Attribute and Size Register
|
||||
}
|
||||
|
||||
var MPU = (*MPU_Type)(unsafe.Pointer(uintptr(0xe000ed90)))
|
||||
|
||||
type (
|
||||
RegionSize uint32
|
||||
AccessPerms uint32
|
||||
Extension uint32
|
||||
)
|
||||
|
||||
// MPU Control Register Definitions
|
||||
const (
|
||||
MPU_CTRL_PRIVDEFENA_Pos = 2 // MPU CTRL: PRIVDEFENA Position
|
||||
MPU_CTRL_PRIVDEFENA_Msk = 1 << MPU_CTRL_PRIVDEFENA_Pos // MPU CTRL: PRIVDEFENA Mask
|
||||
MPU_CTRL_HFNMIENA_Pos = 1 // MPU CTRL: HFNMIENA Position
|
||||
MPU_CTRL_HFNMIENA_Msk = 1 << MPU_CTRL_HFNMIENA_Pos // MPU CTRL: HFNMIENA Mask
|
||||
MPU_CTRL_ENABLE_Pos = 0 // MPU CTRL: ENABLE Position
|
||||
MPU_CTRL_ENABLE_Msk = 1 // MPU CTRL: ENABLE Mask
|
||||
)
|
||||
|
||||
// MPU Region Base Address Register Definitions
|
||||
const (
|
||||
MPU_RBAR_ADDR_Pos = 5 // MPU RBAR: ADDR Position
|
||||
MPU_RBAR_ADDR_Msk = 0x7FFFFFF << MPU_RBAR_ADDR_Pos // MPU RBAR: ADDR Mask
|
||||
MPU_RBAR_VALID_Pos = 4 // MPU RBAR: VALID Position
|
||||
MPU_RBAR_VALID_Msk = 1 << MPU_RBAR_VALID_Pos // MPU RBAR: VALID Mask
|
||||
MPU_RBAR_REGION_Pos = 0 // MPU RBAR: REGION Position
|
||||
MPU_RBAR_REGION_Msk = 0xF // MPU RBAR: REGION Mask
|
||||
)
|
||||
|
||||
// MPU Region Attribute and Size Register Definitions
|
||||
const (
|
||||
MPU_RASR_ATTRS_Pos = 16 // MPU RASR: MPU Region Attribute field Position
|
||||
MPU_RASR_ATTRS_Msk = 0xFFFF << MPU_RASR_ATTRS_Pos // MPU RASR: MPU Region Attribute field Mask
|
||||
MPU_RASR_XN_Pos = 28 // MPU RASR: ATTRS.XN Position
|
||||
MPU_RASR_XN_Msk = 1 << MPU_RASR_XN_Pos // MPU RASR: ATTRS.XN Mask
|
||||
MPU_RASR_AP_Pos = 24 // MPU RASR: ATTRS.AP Position
|
||||
MPU_RASR_AP_Msk = 0x7 << MPU_RASR_AP_Pos // MPU RASR: ATTRS.AP Mask
|
||||
MPU_RASR_TEX_Pos = 19 // MPU RASR: ATTRS.TEX Position
|
||||
MPU_RASR_TEX_Msk = 0x7 << MPU_RASR_TEX_Pos // MPU RASR: ATTRS.TEX Mask
|
||||
MPU_RASR_S_Pos = 18 // MPU RASR: ATTRS.S Position
|
||||
MPU_RASR_S_Msk = 1 << MPU_RASR_S_Pos // MPU RASR: ATTRS.S Mask
|
||||
MPU_RASR_C_Pos = 17 // MPU RASR: ATTRS.C Position
|
||||
MPU_RASR_C_Msk = 1 << MPU_RASR_C_Pos // MPU RASR: ATTRS.C Mask
|
||||
MPU_RASR_B_Pos = 16 // MPU RASR: ATTRS.B Position
|
||||
MPU_RASR_B_Msk = 1 << MPU_RASR_B_Pos // MPU RASR: ATTRS.B Mask
|
||||
MPU_RASR_SRD_Pos = 8 // MPU RASR: Sub-Region Disable Position
|
||||
MPU_RASR_SRD_Msk = 0xFF << MPU_RASR_SRD_Pos // MPU RASR: Sub-Region Disable Mask
|
||||
MPU_RASR_SIZE_Pos = 1 // MPU RASR: Region Size Field Position
|
||||
MPU_RASR_SIZE_Msk = 0x1F << MPU_RASR_SIZE_Pos // MPU RASR: Region Size Field Mask
|
||||
MPU_RASR_ENABLE_Pos = 0 // MPU RASR: Region enable bit Position
|
||||
MPU_RASR_ENABLE_Msk = 1 // MPU RASR: Region enable bit Disable Mask
|
||||
)
|
||||
|
||||
const (
|
||||
SCB_DCISW_WAY_Pos = 30 // SCB DCISW: Way Position
|
||||
SCB_DCISW_WAY_Msk = 3 << SCB_DCISW_WAY_Pos // SCB DCISW: Way Mask
|
||||
SCB_DCISW_SET_Pos = 5 // SCB DCISW: Set Position
|
||||
SCB_DCISW_SET_Msk = 0x1FF << SCB_DCISW_SET_Pos // SCB DCISW: Set Mask
|
||||
)
|
||||
|
||||
const (
|
||||
SCB_DCCISW_WAY_Pos = 30 // SCB DCCISW: Way Position
|
||||
SCB_DCCISW_WAY_Msk = 3 << SCB_DCCISW_WAY_Pos // SCB DCCISW: Way Mask
|
||||
SCB_DCCISW_SET_Pos = 5 // SCB DCCISW: Set Position
|
||||
SCB_DCCISW_SET_Msk = 0x1FF << SCB_DCCISW_SET_Pos // SCB DCCISW: Set Mask
|
||||
)
|
||||
|
||||
const (
|
||||
RGNSZ_32B RegionSize = 0x04 // MPU Region Size 32 Bytes
|
||||
RGNSZ_64B RegionSize = 0x05 // MPU Region Size 64 Bytes
|
||||
RGNSZ_128B RegionSize = 0x06 // MPU Region Size 128 Bytes
|
||||
RGNSZ_256B RegionSize = 0x07 // MPU Region Size 256 Bytes
|
||||
RGNSZ_512B RegionSize = 0x08 // MPU Region Size 512 Bytes
|
||||
RGNSZ_1KB RegionSize = 0x09 // MPU Region Size 1 KByte
|
||||
RGNSZ_2KB RegionSize = 0x0A // MPU Region Size 2 KBytes
|
||||
RGNSZ_4KB RegionSize = 0x0B // MPU Region Size 4 KBytes
|
||||
RGNSZ_8KB RegionSize = 0x0C // MPU Region Size 8 KBytes
|
||||
RGNSZ_16KB RegionSize = 0x0D // MPU Region Size 16 KBytes
|
||||
RGNSZ_32KB RegionSize = 0x0E // MPU Region Size 32 KBytes
|
||||
RGNSZ_64KB RegionSize = 0x0F // MPU Region Size 64 KBytes
|
||||
RGNSZ_128KB RegionSize = 0x10 // MPU Region Size 128 KBytes
|
||||
RGNSZ_256KB RegionSize = 0x11 // MPU Region Size 256 KBytes
|
||||
RGNSZ_512KB RegionSize = 0x12 // MPU Region Size 512 KBytes
|
||||
RGNSZ_1MB RegionSize = 0x13 // MPU Region Size 1 MByte
|
||||
RGNSZ_2MB RegionSize = 0x14 // MPU Region Size 2 MBytes
|
||||
RGNSZ_4MB RegionSize = 0x15 // MPU Region Size 4 MBytes
|
||||
RGNSZ_8MB RegionSize = 0x16 // MPU Region Size 8 MBytes
|
||||
RGNSZ_16MB RegionSize = 0x17 // MPU Region Size 16 MBytes
|
||||
RGNSZ_32MB RegionSize = 0x18 // MPU Region Size 32 MBytes
|
||||
RGNSZ_64MB RegionSize = 0x19 // MPU Region Size 64 MBytes
|
||||
RGNSZ_128MB RegionSize = 0x1A // MPU Region Size 128 MBytes
|
||||
RGNSZ_256MB RegionSize = 0x1B // MPU Region Size 256 MBytes
|
||||
RGNSZ_512MB RegionSize = 0x1C // MPU Region Size 512 MBytes
|
||||
RGNSZ_1GB RegionSize = 0x1D // MPU Region Size 1 GByte
|
||||
RGNSZ_2GB RegionSize = 0x1E // MPU Region Size 2 GBytes
|
||||
RGNSZ_4GB RegionSize = 0x1F // MPU Region Size 4 GBytes
|
||||
)
|
||||
|
||||
const (
|
||||
PERM_NONE AccessPerms = 0 // MPU Access Permission no access
|
||||
PERM_PRIV AccessPerms = 1 // MPU Access Permission privileged access only
|
||||
PERM_URO AccessPerms = 2 // MPU Access Permission unprivileged access read-only
|
||||
PERM_FULL AccessPerms = 3 // MPU Access Permission full access
|
||||
PERM_PRO AccessPerms = 5 // MPU Access Permission privileged access read-only
|
||||
PERM_RO AccessPerms = 6 // MPU Access Permission read-only access
|
||||
)
|
||||
|
||||
const (
|
||||
EXTN_NORMAL Extension = 0
|
||||
EXTN_DEVICE Extension = 2
|
||||
)
|
||||
|
||||
func (mpu *MPU_Type) Enable(enable bool) {
|
||||
if enable {
|
||||
mpu.CTRL.Set(MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_ENABLE_Msk)
|
||||
SystemControl.SHCSR.SetBits(SCB_SHCSR_MEMFAULTENA_Msk)
|
||||
arm.AsmFull(`
|
||||
dsb 0xF
|
||||
isb 0xF
|
||||
`, nil)
|
||||
enableDcache(true)
|
||||
enableIcache(true)
|
||||
} else {
|
||||
enableIcache(false)
|
||||
enableDcache(false)
|
||||
arm.AsmFull(`
|
||||
dmb 0xF
|
||||
`, nil)
|
||||
SystemControl.SHCSR.ClearBits(SCB_SHCSR_MEMFAULTENA_Msk)
|
||||
mpu.CTRL.ClearBits(MPU_CTRL_ENABLE_Msk)
|
||||
}
|
||||
}
|
||||
|
||||
// MPU Region Base Address Register value
|
||||
func (mpu *MPU_Type) SetRBAR(region uint32, baseAddress uint32) {
|
||||
mpu.RBAR.Set((baseAddress & MPU_RBAR_ADDR_Msk) |
|
||||
(region & MPU_RBAR_REGION_Msk) | MPU_RBAR_VALID_Msk)
|
||||
}
|
||||
|
||||
// MPU Region Attribute and Size Register value
|
||||
func (mpu *MPU_Type) SetRASR(size RegionSize, access AccessPerms, ext Extension, exec, share, cache, buffer, disable bool) {
|
||||
boolBit := func(b bool) uint32 {
|
||||
if b {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
attr := ((uint32(ext) << MPU_RASR_TEX_Pos) & MPU_RASR_TEX_Msk) |
|
||||
((boolBit(share) << MPU_RASR_S_Pos) & MPU_RASR_S_Msk) |
|
||||
((boolBit(cache) << MPU_RASR_C_Pos) & MPU_RASR_C_Msk) |
|
||||
((boolBit(buffer) << MPU_RASR_B_Pos) & MPU_RASR_B_Msk)
|
||||
mpu.RASR.Set(((boolBit(!exec) << MPU_RASR_XN_Pos) & MPU_RASR_XN_Msk) |
|
||||
((uint32(access) << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) |
|
||||
(attr & (MPU_RASR_TEX_Msk | MPU_RASR_S_Msk | MPU_RASR_C_Msk | MPU_RASR_B_Msk)) |
|
||||
((boolBit(disable) << MPU_RASR_SRD_Pos) & MPU_RASR_SRD_Msk) |
|
||||
((uint32(size) << MPU_RASR_SIZE_Pos) & MPU_RASR_SIZE_Msk) |
|
||||
MPU_RASR_ENABLE_Msk)
|
||||
}
|
||||
|
||||
func enableIcache(enable bool) {
|
||||
if enable != SystemControl.CCR.HasBits(SCB_CCR_IC_Msk) {
|
||||
if enable {
|
||||
arm.AsmFull(`
|
||||
dsb 0xF
|
||||
isb 0xF
|
||||
`, nil)
|
||||
SystemControl.ICIALLU.Set(0)
|
||||
arm.AsmFull(`
|
||||
dsb 0xF
|
||||
isb 0xF
|
||||
`, nil)
|
||||
SystemControl.CCR.SetBits(SCB_CCR_IC_Msk)
|
||||
arm.AsmFull(`
|
||||
dsb 0xF
|
||||
isb 0xF
|
||||
`, nil)
|
||||
} else {
|
||||
arm.AsmFull(`
|
||||
dsb 0xF
|
||||
isb 0xF
|
||||
`, nil)
|
||||
SystemControl.CCR.ClearBits(SCB_CCR_IC_Msk)
|
||||
SystemControl.ICIALLU.Set(0)
|
||||
arm.AsmFull(`
|
||||
dsb 0xF
|
||||
isb 0xF
|
||||
`, nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func enableDcache(enable bool) {
|
||||
if enable != SystemControl.CCR.HasBits(SCB_CCR_DC_Msk) {
|
||||
if enable {
|
||||
SystemControl.CSSELR.Set(0)
|
||||
arm.AsmFull(`
|
||||
dsb 0xF
|
||||
`, nil)
|
||||
ccsidr := SystemControl.CCSIDR.Get()
|
||||
sets := (ccsidr & SCB_CCSIDR_NUMSETS_Msk) >> SCB_CCSIDR_NUMSETS_Pos
|
||||
for sets != 0 {
|
||||
ways := (ccsidr & SCB_CCSIDR_ASSOCIATIVITY_Msk) >> SCB_CCSIDR_ASSOCIATIVITY_Pos
|
||||
for ways != 0 {
|
||||
SystemControl.DCISW.Set(
|
||||
((sets << SCB_DCISW_SET_Pos) & SCB_DCISW_SET_Msk) |
|
||||
((ways << SCB_DCISW_WAY_Pos) & SCB_DCISW_WAY_Msk))
|
||||
ways--
|
||||
}
|
||||
sets--
|
||||
}
|
||||
arm.AsmFull(`
|
||||
dsb 0xF
|
||||
`, nil)
|
||||
SystemControl.CCR.SetBits(SCB_CCR_DC_Msk)
|
||||
arm.AsmFull(`
|
||||
dsb 0xF
|
||||
isb 0xF
|
||||
`, nil)
|
||||
} else {
|
||||
var (
|
||||
ccsidr volatile.Register32
|
||||
sets volatile.Register32
|
||||
ways volatile.Register32
|
||||
)
|
||||
SystemControl.CSSELR.Set(0)
|
||||
arm.AsmFull(`
|
||||
dsb 0xF
|
||||
`, nil)
|
||||
SystemControl.CCR.ClearBits(SCB_CCR_DC_Msk)
|
||||
arm.AsmFull(`
|
||||
dsb 0xF
|
||||
`, nil)
|
||||
ccsidr.Set(SystemControl.CCSIDR.Get())
|
||||
sets.Set((ccsidr.Get() & SCB_CCSIDR_NUMSETS_Msk) >> SCB_CCSIDR_NUMSETS_Pos)
|
||||
for sets.Get() != 0 {
|
||||
ways.Set((ccsidr.Get() & SCB_CCSIDR_ASSOCIATIVITY_Msk) >> SCB_CCSIDR_ASSOCIATIVITY_Pos)
|
||||
for ways.Get() != 0 {
|
||||
SystemControl.DCCISW.Set(
|
||||
((sets.Get() << SCB_DCCISW_SET_Pos) & SCB_DCCISW_SET_Msk) |
|
||||
((ways.Get() << SCB_DCCISW_WAY_Pos) & SCB_DCCISW_WAY_Msk))
|
||||
ways.Set(ways.Get() - 1)
|
||||
}
|
||||
sets.Set(sets.Get() - 1)
|
||||
}
|
||||
arm.AsmFull(`
|
||||
dsb 0xF
|
||||
isb 0xF
|
||||
`, nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
// +build esp32_coreboard_v2
|
||||
|
||||
package machine
|
||||
|
||||
// Built-in LED on some ESP32 boards.
|
||||
const LED = IO2
|
||||
|
||||
const (
|
||||
CLK Pin = 6
|
||||
CMD Pin = 11
|
||||
IO0 Pin = 0
|
||||
IO1 Pin = 1
|
||||
IO10 Pin = 10
|
||||
IO16 Pin = 16
|
||||
IO17 Pin = 17
|
||||
IO18 Pin = 18
|
||||
IO19 Pin = 19
|
||||
IO2 Pin = 2
|
||||
IO21 Pin = 21
|
||||
IO22 Pin = 22
|
||||
IO23 Pin = 23
|
||||
IO25 Pin = 25
|
||||
IO26 Pin = 26
|
||||
IO27 Pin = 27
|
||||
IO3 Pin = 3
|
||||
IO32 Pin = 32
|
||||
IO33 Pin = 33
|
||||
IO34 Pin = 34
|
||||
IO35 Pin = 35
|
||||
IO36 Pin = 36
|
||||
IO39 Pin = 39
|
||||
IO4 Pin = 4
|
||||
IO5 Pin = 5
|
||||
IO9 Pin = 9
|
||||
RXD Pin = 3
|
||||
SD0 Pin = 7
|
||||
SD1 Pin = 8
|
||||
SD2 Pin = 9
|
||||
SD3 Pin = 10
|
||||
SVN Pin = 39
|
||||
SVP Pin = 36
|
||||
TCK Pin = 13
|
||||
TD0 Pin = 15
|
||||
TDI Pin = 12
|
||||
TMS Pin = 14
|
||||
TXD Pin = 1
|
||||
)
|
||||
|
||||
// SPI pins
|
||||
const (
|
||||
SPI0_SCK_PIN = IO18
|
||||
SPI0_SDO_PIN = IO23
|
||||
SPI0_SDI_PIN = IO19
|
||||
SPI0_CS0_PIN = IO5
|
||||
)
|
||||
|
||||
// I2C pins
|
||||
const (
|
||||
SDA_PIN = IO21
|
||||
SCL_PIN = IO22
|
||||
)
|
||||
|
||||
// ADC pins
|
||||
const (
|
||||
ADC0 Pin = IO34
|
||||
ADC1 Pin = IO35
|
||||
ADC2 Pin = IO36
|
||||
ADC3 Pin = IO39
|
||||
)
|
||||
|
||||
// UART0 pins
|
||||
const (
|
||||
UART_TX_PIN = IO1
|
||||
UART_RX_PIN = IO3
|
||||
)
|
||||
|
||||
// UART1 pins
|
||||
const (
|
||||
UART1_TX_PIN = IO9
|
||||
UART1_RX_PIN = IO10
|
||||
)
|
||||
|
||||
// PWM pins
|
||||
const (
|
||||
PWM0_PIN Pin = IO2
|
||||
PWM1_PIN Pin = IO0
|
||||
PWM2_PIN Pin = IO4
|
||||
)
|
||||
@@ -1,6 +0,0 @@
|
||||
// +build esp32_wroom_32
|
||||
|
||||
package machine
|
||||
|
||||
// Blue LED on the ESP32-WROOM-32 module.
|
||||
const LED = Pin(2)
|
||||
@@ -178,6 +178,22 @@ const (
|
||||
SPI_SDO_PIN = SPI0_SDO_PIN //
|
||||
)
|
||||
|
||||
var (
|
||||
SPI1 = SPI{
|
||||
Bus: stm32.SPI2,
|
||||
AltFuncSelector: stm32.AF5_SPI1_SPI2,
|
||||
}
|
||||
SPI2 = SPI{
|
||||
Bus: stm32.SPI3,
|
||||
AltFuncSelector: stm32.AF6_SPI3,
|
||||
}
|
||||
SPI3 = SPI{
|
||||
Bus: stm32.SPI1,
|
||||
AltFuncSelector: stm32.AF5_SPI1_SPI2,
|
||||
}
|
||||
SPI0 = SPI1
|
||||
)
|
||||
|
||||
func initSPI() {}
|
||||
|
||||
// -- I2C ----------------------------------------------------------------------
|
||||
@@ -186,11 +202,11 @@ const (
|
||||
// #===========#==========#==============#==============#=======#=======#
|
||||
// | Interface | Hardware | Bus(Freq) | SDA/SCL Pins | AltFn | Alias |
|
||||
// #===========#==========#==============#==============#=======#=======#
|
||||
// | I2C1 | I2C1 | | D14/D15 | | ~ |
|
||||
// | I2C2 | I2C2 | | D0/D1 | | ~ |
|
||||
// | I2C3 | I2C1 | | D9/D10 | | ~ |
|
||||
// | I2C1 | I2C1 | APB1(42 MHz) | D14/D15 | 4 | ~ |
|
||||
// | I2C2 | I2C2 | APB1(42 MHz) | D0/D1 | 4 | ~ |
|
||||
// | I2C3 | I2C1 | APB1(42 MHz) | D9/D10 | 4 | ~ |
|
||||
// | --------- | -------- | ------------ | ------------ | ----- | ----- |
|
||||
// | I2C0 | I2C1 | | D14/D15 | | I2C1 |
|
||||
// | I2C0 | I2C1 | APB1(42 MHz) | D14/D15 | 4 | I2C1 |
|
||||
// #===========#==========#==============#==============#=======#=======#
|
||||
NUM_I2C_INTERFACES = 3
|
||||
|
||||
@@ -210,4 +226,20 @@ const (
|
||||
I2C_SCL_PIN = I2C0_SCL_PIN //
|
||||
)
|
||||
|
||||
var (
|
||||
I2C1 = I2C{
|
||||
Bus: stm32.I2C1,
|
||||
AltFuncSelector: stm32.AF4_I2C1_2_3,
|
||||
}
|
||||
I2C2 = I2C{
|
||||
Bus: stm32.I2C2,
|
||||
AltFuncSelector: stm32.AF4_I2C1_2_3,
|
||||
}
|
||||
I2C3 = I2C{
|
||||
Bus: stm32.I2C1,
|
||||
AltFuncSelector: stm32.AF4_I2C1_2_3,
|
||||
}
|
||||
I2C0 = I2C1
|
||||
)
|
||||
|
||||
func initI2C() {}
|
||||
|
||||
@@ -19,3 +19,17 @@ const (
|
||||
|
||||
// Onboard blue LED (on the AI-Thinker module).
|
||||
const LED = D4
|
||||
|
||||
// SPI pins
|
||||
const (
|
||||
SPI0_SCK_PIN = D5
|
||||
SPI0_SDO_PIN = D7
|
||||
SPI0_SDI_PIN = D6
|
||||
SPI0_CS0_PIN = D8
|
||||
)
|
||||
|
||||
// I2C pins
|
||||
const (
|
||||
SDA_PIN = D2
|
||||
SCL_PIN = D1
|
||||
)
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
// +build sam,atsamd21,qtpy
|
||||
|
||||
package machine
|
||||
|
||||
import (
|
||||
"device/sam"
|
||||
"runtime/interrupt"
|
||||
)
|
||||
|
||||
// used to reset into bootloader
|
||||
const RESET_MAGIC_VALUE = 0xf01669ef
|
||||
|
||||
// GPIO Pins
|
||||
const (
|
||||
D0 = PA02 // PWM available
|
||||
D1 = PA03
|
||||
D2 = PA04 // PWM available
|
||||
D3 = PA05 // PWM available
|
||||
D4 = PA16 // PWM available
|
||||
D5 = PA17 // PWM available
|
||||
D6 = PA06
|
||||
D7 = PA07
|
||||
D8 = PA11
|
||||
D9 = PA09
|
||||
D10 = PA10
|
||||
D11 = PA18
|
||||
D12 = PA15
|
||||
D13 = PA27
|
||||
D14 = PA23
|
||||
D15 = PA19
|
||||
D16 = PA22
|
||||
D17 = PA08
|
||||
)
|
||||
|
||||
// Analog pins
|
||||
const (
|
||||
A0 = D1
|
||||
A1 = D1
|
||||
A2 = D2
|
||||
A3 = D3
|
||||
A4 = D4
|
||||
)
|
||||
|
||||
const (
|
||||
LED = D13
|
||||
)
|
||||
|
||||
// UART0 aka USBCDC pins
|
||||
const (
|
||||
USBCDC_DM_PIN = PA24
|
||||
USBCDC_DP_PIN = PA25
|
||||
)
|
||||
|
||||
// UART1 pins
|
||||
const (
|
||||
UART_TX_PIN = D6
|
||||
UART_RX_PIN = D7
|
||||
)
|
||||
|
||||
// UART1 on the QT Py M0.
|
||||
var (
|
||||
UART1 = UART{
|
||||
Buffer: NewRingBuffer(),
|
||||
Bus: sam.SERCOM0_USART,
|
||||
SERCOM: 0,
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
UART1.Interrupt = interrupt.New(sam.IRQ_SERCOM0, UART1.handleInterrupt)
|
||||
}
|
||||
|
||||
// SPI pins
|
||||
const (
|
||||
SPI0_SCK_PIN = D8
|
||||
SPI0_SDO_PIN = D10
|
||||
SPI0_SDI_PIN = D9
|
||||
)
|
||||
|
||||
// SPI on the QT Py M0.
|
||||
var (
|
||||
SPI0 = SPI{
|
||||
Bus: sam.SERCOM0_SPI,
|
||||
SERCOM: 0,
|
||||
}
|
||||
)
|
||||
|
||||
// I2C pins
|
||||
const (
|
||||
SDA_PIN = D4 // SDA
|
||||
SCL_PIN = D5 // SCL
|
||||
)
|
||||
|
||||
// I2C on the QT Py M0.
|
||||
var (
|
||||
I2C0 = I2C{
|
||||
Bus: sam.SERCOM2_I2CM,
|
||||
SERCOM: 2,
|
||||
}
|
||||
)
|
||||
|
||||
// I2S pins
|
||||
const (
|
||||
I2S_SCK_PIN = PA10
|
||||
I2S_SD_PIN = PA08
|
||||
I2S_WS_PIN = NoPin // TODO: figure out what this is on QT Py M0.
|
||||
)
|
||||
|
||||
// USB CDC identifiers
|
||||
const (
|
||||
usb_STRING_PRODUCT = "Adafruit QTPy M0"
|
||||
usb_STRING_MANUFACTURER = "Adafruit"
|
||||
)
|
||||
|
||||
var (
|
||||
usb_VID uint16 = 0x239A
|
||||
usb_PID uint16 = 0x80CB
|
||||
)
|
||||
@@ -0,0 +1,262 @@
|
||||
// +build teensy40
|
||||
|
||||
package machine
|
||||
|
||||
import (
|
||||
"device/nxp"
|
||||
"runtime/interrupt"
|
||||
)
|
||||
|
||||
// Digital pins
|
||||
const (
|
||||
// = Pin // [Pad]: Alt Func 0 Alt Func 1 Alt Func 2 Alt Func 3 Alt Func 4 Alt Func 5 Alt Func 6 Alt Func 7 Alt Func 8 Alt Func 9
|
||||
// = ---- ----------- --------------- --------------- --------------- -------------- -------------------- ---------- -------------------- --------------------- --------------------- ----------------
|
||||
D0 = PA3 // [AD_B0_03]: FLEXCAN2_RX XBAR1_INOUT17 LPUART6_RX USB_OTG1_OC FLEXPWM1_PWMX01 GPIO1_IO03 REF_CLK_24M LPSPI3_PCS0 ~ ~
|
||||
D1 = PA2 // [AD_B0_02]: FLEXCAN2_TX XBAR1_INOUT16 LPUART6_TX USB_OTG1_PWR FLEXPWM1_PWMX00 GPIO1_IO02 LPI2C1_HREQ LPSPI3_SDI ~ ~
|
||||
D2 = PD4 // [EMC_04]: SEMC_DATA04 FLEXPWM4_PWMA02 SAI2_TX_DATA XBAR1_INOUT06 FLEXIO1_FLEXIO04 GPIO4_IO04 ~ ~ ~ ~
|
||||
D3 = PD5 // [EMC_05]: SEMC_DATA05 FLEXPWM4_PWMB02 SAI2_TX_SYNC XBAR1_INOUT07 FLEXIO1_FLEXIO05 GPIO4_IO05 ~ ~ ~ ~
|
||||
D4 = PD6 // [EMC_06]: SEMC_DATA06 FLEXPWM2_PWMA00 SAI2_TX_BCLK XBAR1_INOUT08 FLEXIO1_FLEXIO06 GPIO4_IO06 ~ ~ ~ ~
|
||||
D5 = PD8 // [EMC_08]: SEMC_DM00 FLEXPWM2_PWMA01 SAI2_RX_DATA XBAR1_INOUT17 FLEXIO1_FLEXIO08 GPIO4_IO08 ~ ~ ~ ~
|
||||
D6 = PB10 // [B0_10]: LCD_DATA06 QTIMER4_TIMER1 FLEXPWM2_PWMA02 SAI1_TX_DATA03 FLEXIO2_FLEXIO10 GPIO2_IO10 SRC_BOOT_CFG06 ENET2_CRS ~ ~
|
||||
D7 = PB17 // [B1_01]: LCD_DATA13 XBAR1_INOUT15 LPUART4_RX SAI1_TX_DATA00 FLEXIO2_FLEXIO17 GPIO2_IO17 FLEXPWM1_PWMB03 ENET2_RDATA00 FLEXIO3_FLEXIO17 ~
|
||||
D8 = PB16 // [B1_00]: LCD_DATA12 XBAR1_INOUT14 LPUART4_TX SAI1_RX_DATA00 FLEXIO2_FLEXIO16 GPIO2_IO16 FLEXPWM1_PWMA03 ENET2_RX_ER FLEXIO3_FLEXIO16 ~
|
||||
D9 = PB11 // [B0_11]: LCD_DATA07 QTIMER4_TIMER2 FLEXPWM2_PWMB02 SAI1_TX_DATA02 FLEXIO2_FLEXIO11 GPIO2_IO11 SRC_BOOT_CFG07 ENET2_COL ~ ~
|
||||
D10 = PB0 // [B0_00]: LCD_CLK QTIMER1_TIMER0 MQS_RIGHT LPSPI4_PCS0 FLEXIO2_FLEXIO00 GPIO2_IO00 SEMC_CSX01 ENET2_MDC ~ ~
|
||||
D11 = PB2 // [B0_02]: LCD_HSYNC QTIMER1_TIMER2 FLEXCAN1_TX LPSPI4_SDO FLEXIO2_FLEXIO02 GPIO2_IO02 SEMC_CSX03 ENET2_1588_EVENT0_OUT ~ ~
|
||||
D12 = PB1 // [B0_01]: LCD_ENABLE QTIMER1_TIMER1 MQS_LEFT LPSPI4_SDI FLEXIO2_FLEXIO01 GPIO2_IO01 SEMC_CSX02 ENET2_MDIO ~ ~
|
||||
D13 = PB3 // [B0_03]: LCD_VSYNC QTIMER2_TIMER0 FLEXCAN1_RX LPSPI4_SCK FLEXIO2_FLEXIO03 GPIO2_IO03 WDOG2_RESET_B_DEB ENET2_1588_EVENT0_IN ~ ~
|
||||
D14 = PA18 // [AD_B1_02]: USB_OTG1_ID QTIMER3_TIMER2 LPUART2_TX SPDIF_OUT ENET_1588_EVENT2_OUT GPIO1_IO18 USDHC1_CD_B KPP_ROW06 GPT2_CLK FLEXIO3_FLEXIO02
|
||||
D15 = PA19 // [AD_B1_03]: USB_OTG1_OC QTIMER3_TIMER3 LPUART2_RX SPDIF_IN ENET_1588_EVENT2_IN GPIO1_IO19 USDHC2_CD_B KPP_COL06 GPT2_CAPTURE1 FLEXIO3_FLEXIO03
|
||||
D16 = PA23 // [AD_B1_07]: FLEXSPIB_DATA00 LPI2C3_SCL LPUART3_RX SPDIF_EXT_CLK CSI_HSYNC GPIO1_IO23 USDHC2_DATA3 KPP_COL04 GPT2_COMPARE3 FLEXIO3_FLEXIO07
|
||||
D17 = PA22 // [AD_B1_06]: FLEXSPIB_DATA01 LPI2C3_SDA LPUART3_TX SPDIF_LOCK CSI_VSYNC GPIO1_IO22 USDHC2_DATA2 KPP_ROW04 GPT2_COMPARE2 FLEXIO3_FLEXIO06
|
||||
D18 = PA17 // [AD_B1_01]: USB_OTG1_PWR QTIMER3_TIMER1 LPUART2_RTS_B LPI2C1_SDA CCM_PMIC_READY GPIO1_IO17 USDHC1_VSELECT KPP_COL07 ENET2_1588_EVENT0_IN FLEXIO3_FLEXIO01
|
||||
D19 = PA16 // [AD_B1_00]: USB_OTG2_ID QTIMER3_TIMER0 LPUART2_CTS_B LPI2C1_SCL WDOG1_B GPIO1_IO16 USDHC1_WP KPP_ROW07 ENET2_1588_EVENT0_OUT FLEXIO3_FLEXIO00
|
||||
D20 = PA26 // [AD_B1_10]: FLEXSPIA_DATA03 WDOG1_B LPUART8_TX SAI1_RX_SYNC CSI_DATA07 GPIO1_IO26 USDHC2_WP KPP_ROW02 ENET2_1588_EVENT1_OUT FLEXIO3_FLEXIO10
|
||||
D21 = PA27 // [AD_B1_11]: FLEXSPIA_DATA02 EWM_OUT_B LPUART8_RX SAI1_RX_BCLK CSI_DATA06 GPIO1_IO27 USDHC2_RESET_B KPP_COL02 ENET2_1588_EVENT1_IN FLEXIO3_FLEXIO11
|
||||
D22 = PA24 // [AD_B1_08]: FLEXSPIA_SS1_B FLEXPWM4_PWMA00 FLEXCAN1_TX CCM_PMIC_READY CSI_DATA09 GPIO1_IO24 USDHC2_CMD KPP_ROW03 FLEXIO3_FLEXIO08 ~
|
||||
D23 = PA25 // [AD_B1_09]: FLEXSPIA_DQS FLEXPWM4_PWMA01 FLEXCAN1_RX SAI1_MCLK CSI_DATA08 GPIO1_IO25 USDHC2_CLK KPP_COL03 FLEXIO3_FLEXIO09 ~
|
||||
D24 = PA12 // [AD_B0_12]: LPI2C4_SCL CCM_PMIC_READY LPUART1_TX WDOG2_WDOG_B FLEXPWM1_PWMX02 GPIO1_IO12 ENET_1588_EVENT1_OUT NMI_GLUE_NMI ~ ~
|
||||
D25 = PA13 // [AD_B0_13]: LPI2C4_SDA GPT1_CLK LPUART1_RX EWM_OUT_B FLEXPWM1_PWMX03 GPIO1_IO13 ENET_1588_EVENT1_IN REF_CLK_24M ~ ~
|
||||
D26 = PA30 // [AD_B1_14]: FLEXSPIA_SCLK ACMP_OUT02 LPSPI3_SDO SAI1_TX_BCLK CSI_DATA03 GPIO1_IO30 USDHC2_DATA6 KPP_ROW00 ENET2_1588_EVENT3_OUT FLEXIO3_FLEXIO14
|
||||
D27 = PA31 // [AD_B1_15]: FLEXSPIA_SS0_B ACMP_OUT03 LPSPI3_SCK SAI1_TX_SYNC CSI_DATA02 GPIO1_IO31 USDHC2_DATA7 KPP_COL00 ENET2_1588_EVENT3_IN FLEXIO3_FLEXIO15
|
||||
D28 = PC18 // [EMC_32]: SEMC_DATA10 FLEXPWM3_PWMB01 LPUART7_RX CCM_PMIC_RDY CSI_DATA21 GPIO3_IO18 ENET2_TX_EN ~ ~ ~
|
||||
D29 = PD31 // [EMC_31]: SEMC_DATA09 FLEXPWM3_PWMA01 LPUART7_TX LPSPI1_PCS1 CSI_DATA22 GPIO4_IO31 ENET2_TDATA01 ~ ~ ~
|
||||
D30 = PC23 // [EMC_37]: SEMC_DATA15 XBAR1_IN23 GPT1_COMPARE3 SAI3_MCLK CSI_DATA16 GPIO3_IO23 USDHC2_WP ENET2_RX_EN FLEXCAN3_RX ~
|
||||
D31 = PC22 // [EMC_36]: SEMC_DATA14 XBAR1_IN22 GPT1_COMPARE2 SAI3_TX_DATA CSI_DATA17 GPIO3_IO22 USDHC1_WP ENET2_RDATA01 FLEXCAN3_TX ~
|
||||
D32 = PB12 // [B0_12]: LCD_DATA08 XBAR1_INOUT10 ARM_TRACE_CLK SAI1_TX_DATA01 FLEXIO2_FLEXIO12 GPIO2_IO12 SRC_BOOT_CFG08 ENET2_TDATA00 ~ ~
|
||||
D33 = PD7 // [EMC_07]: SEMC_DATA07 FLEXPWM2_PWMB00 SAI2_MCLK XBAR1_INOUT09 FLEXIO1_FLEXIO07 GPIO4_IO07 ~ ~ ~ ~
|
||||
D34 = PC15 // [SD_B0_03]: USDHC1_DATA1 FLEXPWM1_PWMB01 LPUART8_RTS_B XBAR1_INOUT07 LPSPI1_SDI GPIO3_IO15 ENET2_RDATA00 SEMC_CLK6 ~ ~
|
||||
D35 = PC14 // [SD_B0_02]: USDHC1_DATA0 FLEXPWM1_PWMA01 LPUART8_CTS_B XBAR1_INOUT06 LPSPI1_SDO GPIO3_IO14 ENET2_RX_ER SEMC_CLK5 ~ ~
|
||||
D36 = PC13 // [SD_B0_01]: USDHC1_CLK FLEXPWM1_PWMB00 LPI2C3_SDA XBAR1_INOUT05 LPSPI1_PCS0 GPIO3_IO13 FLEXSPIB_SS1_B ENET2_TX_CLK ENET2_REF_CLK2 ~
|
||||
D37 = PC12 // [SD_B0_00]: USDHC1_CMD FLEXPWM1_PWMA00 LPI2C3_SCL XBAR1_INOUT04 LPSPI1_SCK GPIO3_IO12 FLEXSPIA_SS1_B ENET2_TX_EN SEMC_DQS4 ~
|
||||
D38 = PC17 // [SD_B0_05]: USDHC1_DATA3 FLEXPWM1_PWMB02 LPUART8_RX XBAR1_INOUT09 FLEXSPIB_DQS GPIO3_IO17 CCM_CLKO2 ENET2_RX_EN ~ ~
|
||||
D39 = PC16 // [SD_B0_04]: USDHC1_DATA2 FLEXPWM1_PWMA02 LPUART8_TX XBAR1_INOUT08 FLEXSPIB_SS0_B GPIO3_IO16 CCM_CLKO1 ENET2_RDATA01 ~ ~
|
||||
)
|
||||
|
||||
// Analog pins
|
||||
const (
|
||||
// = Pin // Dig | [Pad] {ADC1/ADC2}
|
||||
A0 = PA18 // D14 | [AD_B1_02] { 7 / 7 }
|
||||
A1 = PA19 // D15 | [AD_B1_03] { 8 / 8 }
|
||||
A2 = PA23 // D16 | [AD_B1_07] { 12 / 12 }
|
||||
A3 = PA22 // D17 | [AD_B1_06] { 11 / 11 }
|
||||
A4 = PA17 // D18 | [AD_B1_01] { 6 / 6 }
|
||||
A5 = PA16 // D19 | [AD_B1_00] { 5 / 5 }
|
||||
A6 = PA26 // D20 | [AD_B1_10] { 15 / 15 }
|
||||
A7 = PA27 // D21 | [AD_B1_11] { 0 / 0 }
|
||||
A8 = PA24 // D22 | [AD_B1_08] { 13 / 13 }
|
||||
A9 = PA25 // D23 | [AD_B1_09] { 14 / 14 }
|
||||
A10 = PA12 // D24 | [AD_B0_12] { 1 / - }
|
||||
A11 = PA13 // D25 | [AD_B0_13] { 2 / - }
|
||||
A12 = PA30 // D26 | [AD_B1_14] { - / 3 }
|
||||
A13 = PA31 // D27 | [AD_B1_15] { - / 4 }
|
||||
)
|
||||
|
||||
// Default peripheral pins
|
||||
const (
|
||||
LED = D13
|
||||
|
||||
UART_RX_PIN = UART1_RX_PIN // D0
|
||||
UART_TX_PIN = UART1_TX_PIN // D1
|
||||
|
||||
SPI_SDI_PIN = SPI1_SDI_PIN // D12
|
||||
SPI_SDO_PIN = SPI1_SDO_PIN // D11
|
||||
SPI_SCK_PIN = SPI1_SCK_PIN // D13
|
||||
SPI_CS_PIN = SPI1_CS_PIN // D10
|
||||
|
||||
I2C_SDA_PIN = I2C1_SDA_PIN // D18/A4
|
||||
I2C_SCL_PIN = I2C1_SCL_PIN // D19/A5
|
||||
)
|
||||
|
||||
func init() {
|
||||
// register any interrupt handlers for this board's peripherals
|
||||
UART1.Interrupt = interrupt.New(nxp.IRQ_LPUART6, UART1.handleInterrupt)
|
||||
UART2.Interrupt = interrupt.New(nxp.IRQ_LPUART4, UART2.handleInterrupt)
|
||||
UART3.Interrupt = interrupt.New(nxp.IRQ_LPUART2, UART3.handleInterrupt)
|
||||
UART4.Interrupt = interrupt.New(nxp.IRQ_LPUART3, UART4.handleInterrupt)
|
||||
UART5.Interrupt = interrupt.New(nxp.IRQ_LPUART8, UART5.handleInterrupt)
|
||||
UART6.Interrupt = interrupt.New(nxp.IRQ_LPUART1, UART6.handleInterrupt)
|
||||
UART7.Interrupt = interrupt.New(nxp.IRQ_LPUART7, UART7.handleInterrupt)
|
||||
}
|
||||
|
||||
// #=====================================================#
|
||||
// | UART |
|
||||
// #===========#===========#=============#===============#
|
||||
// | Interface | Hardware | Clock(Freq) | RX/TX : Alt |
|
||||
// #===========#===========#=============#=========-=====#
|
||||
// | UART1 | LPUART6 | OSC(24 MHz) | D0/D1 : 2/2 |
|
||||
// | UART2 | LPUART4 | OSC(24 MHz) | D7/D8 : 2/2 |
|
||||
// | UART3 | LPUART2 | OSC(24 MHz) | D15/D14 : 2/2 |
|
||||
// | UART4 | LPUART3 | OSC(24 MHz) | D16/D17 : 2/2 |
|
||||
// | UART5 | LPUART8 | OSC(24 MHz) | D21/D20 : 2/2 |
|
||||
// | UART6 | LPUART1 | OSC(24 MHz) | D25/D24 : 2/2 |
|
||||
// | UART7 | LPUART7 | OSC(24 MHz) | D28/D29 : 2/2 |
|
||||
// #===========#===========#=============#=========-=====#
|
||||
const (
|
||||
UART1_RX_PIN = D0
|
||||
UART1_TX_PIN = D1
|
||||
|
||||
UART2_RX_PIN = D7
|
||||
UART2_TX_PIN = D8
|
||||
|
||||
UART3_RX_PIN = D15
|
||||
UART3_TX_PIN = D14
|
||||
|
||||
UART4_RX_PIN = D16
|
||||
UART4_TX_PIN = D17
|
||||
|
||||
UART5_RX_PIN = D21
|
||||
UART5_TX_PIN = D20
|
||||
|
||||
UART6_RX_PIN = D25
|
||||
UART6_TX_PIN = D24
|
||||
|
||||
UART7_RX_PIN = D28
|
||||
UART7_TX_PIN = D29
|
||||
)
|
||||
|
||||
var (
|
||||
UART1 = UART{
|
||||
Buffer: NewRingBuffer(),
|
||||
Bus: nxp.LPUART6,
|
||||
muxRX: muxSelect{ // D0 (PA3 [AD_B0_03])
|
||||
mux: nxp.IOMUXC_LPUART6_RX_SELECT_INPUT_DAISY_GPIO_AD_B0_03_ALT2,
|
||||
sel: &nxp.IOMUXC.LPUART6_RX_SELECT_INPUT,
|
||||
},
|
||||
muxTX: muxSelect{ // D1 (PA2 [AD_B0_02])
|
||||
mux: nxp.IOMUXC_LPUART6_TX_SELECT_INPUT_DAISY_GPIO_AD_B0_02_ALT2,
|
||||
sel: &nxp.IOMUXC.LPUART6_TX_SELECT_INPUT,
|
||||
},
|
||||
}
|
||||
UART2 = UART{
|
||||
Buffer: NewRingBuffer(),
|
||||
Bus: nxp.LPUART4,
|
||||
muxRX: muxSelect{ // D7 (PB17 [B1_01])
|
||||
mux: nxp.IOMUXC_LPUART4_RX_SELECT_INPUT_DAISY_GPIO_B1_01_ALT2,
|
||||
sel: &nxp.IOMUXC.LPUART4_RX_SELECT_INPUT,
|
||||
},
|
||||
muxTX: muxSelect{ // D8 (PB16 [B1_00])
|
||||
mux: nxp.IOMUXC_LPUART4_TX_SELECT_INPUT_DAISY_GPIO_B1_00_ALT2,
|
||||
sel: &nxp.IOMUXC.LPUART4_TX_SELECT_INPUT,
|
||||
},
|
||||
}
|
||||
UART3 = UART{
|
||||
Buffer: NewRingBuffer(),
|
||||
Bus: nxp.LPUART2,
|
||||
muxRX: muxSelect{ // D15 (PA19 [AD_B1_03])
|
||||
mux: nxp.IOMUXC_LPUART2_RX_SELECT_INPUT_DAISY_GPIO_AD_B1_03_ALT2,
|
||||
sel: &nxp.IOMUXC.LPUART2_RX_SELECT_INPUT,
|
||||
},
|
||||
muxTX: muxSelect{ // D14 (PA18 [AD_B1_02])
|
||||
mux: nxp.IOMUXC_LPUART2_TX_SELECT_INPUT_DAISY_GPIO_AD_B1_02_ALT2,
|
||||
sel: &nxp.IOMUXC.LPUART2_TX_SELECT_INPUT,
|
||||
},
|
||||
}
|
||||
UART4 = UART{
|
||||
Buffer: NewRingBuffer(),
|
||||
Bus: nxp.LPUART3,
|
||||
muxRX: muxSelect{ // D16 (PA23 [AD_B1_07])
|
||||
mux: nxp.IOMUXC_LPUART3_RX_SELECT_INPUT_DAISY_GPIO_AD_B1_07_ALT2,
|
||||
sel: &nxp.IOMUXC.LPUART3_RX_SELECT_INPUT,
|
||||
},
|
||||
muxTX: muxSelect{ // D17 (PA22 [AD_B1_06])
|
||||
mux: nxp.IOMUXC_LPUART3_TX_SELECT_INPUT_DAISY_GPIO_AD_B1_06_ALT2,
|
||||
sel: &nxp.IOMUXC.LPUART3_TX_SELECT_INPUT,
|
||||
},
|
||||
}
|
||||
UART5 = UART{
|
||||
Buffer: NewRingBuffer(),
|
||||
Bus: nxp.LPUART8,
|
||||
muxRX: muxSelect{ // D21 (PA27 [AD_B1_11])
|
||||
mux: nxp.IOMUXC_LPUART8_RX_SELECT_INPUT_DAISY_GPIO_AD_B1_11_ALT2,
|
||||
sel: &nxp.IOMUXC.LPUART8_RX_SELECT_INPUT,
|
||||
},
|
||||
muxTX: muxSelect{ // D20 (PA26 [AD_B1_10])
|
||||
mux: nxp.IOMUXC_LPUART8_TX_SELECT_INPUT_DAISY_GPIO_AD_B1_10_ALT2,
|
||||
sel: &nxp.IOMUXC.LPUART8_TX_SELECT_INPUT,
|
||||
},
|
||||
}
|
||||
UART6 = UART{
|
||||
Buffer: NewRingBuffer(),
|
||||
Bus: nxp.LPUART1,
|
||||
// LPUART1 not connected via IOMUXC
|
||||
// RX: D24 (PA12 [AD_B0_12])
|
||||
// TX: D25 (PA13 [AD_B0_13])
|
||||
}
|
||||
UART7 = UART{
|
||||
Buffer: NewRingBuffer(),
|
||||
Bus: nxp.LPUART7,
|
||||
muxRX: muxSelect{ // D28 (PC18 [EMC_32])
|
||||
mux: nxp.IOMUXC_LPUART7_RX_SELECT_INPUT_DAISY_GPIO_EMC_32_ALT2,
|
||||
sel: &nxp.IOMUXC.LPUART7_RX_SELECT_INPUT,
|
||||
},
|
||||
muxTX: muxSelect{ // D29 (PD31 [EMC_31])
|
||||
mux: nxp.IOMUXC_LPUART7_TX_SELECT_INPUT_DAISY_GPIO_EMC_31_ALT2,
|
||||
sel: &nxp.IOMUXC.LPUART7_TX_SELECT_INPUT,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// #===========#==========#===============#===========================#
|
||||
// | Interface | Hardware | Clock(Freq) | SDI/SDO/SCK/CS : Alt |
|
||||
// #===========#==========#===============#=================-=========#
|
||||
// | SPI1 | LPSPI4 | PLL2(132 MHz) | D12/D11/D13/D10 : 3/3/3/3 |
|
||||
// | SPI2 | LPSPI3 | PLL2(132 MHz) | D1/D26/D27/D0 : 7/2/2/7 |
|
||||
// | SPI3 | LPSPI1 | PLL2(132 MHz) | D34/D35/D37/D36 : 4/4/4/4 |
|
||||
// #===========#==========#===============#=================-=========#
|
||||
const (
|
||||
SPI1_SDI_PIN = D12
|
||||
SPI1_SDO_PIN = D11
|
||||
SPI1_SCK_PIN = D13
|
||||
SPI1_CS_PIN = D10
|
||||
|
||||
SPI2_SDI_PIN = D1
|
||||
SPI2_SDO_PIN = D26
|
||||
SPI2_SCK_PIN = D27
|
||||
SPI2_CS_PIN = D0
|
||||
|
||||
SPI3_SDI_PIN = D34
|
||||
SPI3_SDO_PIN = D35
|
||||
SPI3_SCK_PIN = D37
|
||||
SPI3_CS_PIN = D36
|
||||
)
|
||||
|
||||
// #====================================================#
|
||||
// | I2C |
|
||||
// #===========#==========#=============#===============#
|
||||
// | Interface | Hardware | Clock(Freq) | SDA/SCL : Alt |
|
||||
// #===========#==========#=============#=========-=====#
|
||||
// | I2C1 | LPI2C1 | OSC(24 MHz) | D18/D19 : 3/3 |
|
||||
// | I2C2 | LPI2C3 | OSC(24 MHz) | D17/D16 : 1/1 |
|
||||
// | I2C3 | LPI2C4 | OSC(24 MHz) | D25/D24 : 0/0 |
|
||||
// #===========#==========#=============#=========-=====#
|
||||
const (
|
||||
I2C1_SDA_PIN = D18
|
||||
I2C1_SCL_PIN = D19
|
||||
|
||||
I2C2_SDA_PIN = D17
|
||||
I2C2_SCL_PIN = D16
|
||||
|
||||
I2C3_SDA_PIN = D25
|
||||
I2C3_SCL_PIN = D24
|
||||
)
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// +build avr nrf sam stm32,!stm32f4 fe310 k210
|
||||
// +build avr nrf sam stm32,!stm32f407 fe310 k210
|
||||
|
||||
package machine
|
||||
|
||||
|
||||
@@ -165,7 +165,8 @@ func findPinPadMapping(sercom uint8, pin Pin) (pinMode PinMode, pad uint32, ok b
|
||||
}
|
||||
|
||||
// SetInterrupt sets an interrupt to be executed when a particular pin changes
|
||||
// state.
|
||||
// state. The pin should already be configured as an input, including a pull up
|
||||
// or down if no external pull is provided.
|
||||
//
|
||||
// This call will replace a previously set callback on this pin. You can pass a
|
||||
// nil func to unset the pin change interrupt. If you do so, the change
|
||||
|
||||
@@ -353,7 +353,8 @@ func findPinPadMapping(sercom uint8, pin Pin) (pinMode PinMode, pad uint32, ok b
|
||||
}
|
||||
|
||||
// SetInterrupt sets an interrupt to be executed when a particular pin changes
|
||||
// state.
|
||||
// state. The pin should already be configured as an input, including a pull up
|
||||
// or down if no external pull is provided.
|
||||
//
|
||||
// This call will replace a previously set callback on this pin. You can pass a
|
||||
// nil func to unset the pin change interrupt. If you do so, the change
|
||||
@@ -1331,12 +1332,13 @@ func (spi SPI) Configure(config SPIConfig) error {
|
||||
|
||||
// Determine the input pinout (for SDI).
|
||||
var dataInPinout uint32
|
||||
SDIPinMode, SDIPad, ok := findPinPadMapping(spi.SERCOM, config.SDI)
|
||||
var SDIPinMode PinMode
|
||||
if config.SDI != NoPin {
|
||||
var ok bool
|
||||
SDIPinMode, dataInPinout, ok = findPinPadMapping(spi.SERCOM, config.SDI)
|
||||
if !ok {
|
||||
return ErrInvalidInputPin
|
||||
}
|
||||
dataInPinout = SDIPad // mapped directly
|
||||
}
|
||||
|
||||
// Determine the output pinout (for SDO/SCK).
|
||||
|
||||
@@ -310,7 +310,7 @@ type SPIConfig struct {
|
||||
// Configure and make the SPI peripheral ready to use.
|
||||
func (spi SPI) Configure(config SPIConfig) error {
|
||||
if config.Frequency == 0 {
|
||||
config.Frequency = 1e6 // default to 1MHz
|
||||
config.Frequency = 4e6 // default to 4MHz
|
||||
}
|
||||
|
||||
// Configure the SPI clock. This assumes a peripheral clock of 80MHz.
|
||||
|
||||
@@ -107,6 +107,15 @@ func (p Pin) Configure(config PinConfig) {
|
||||
}
|
||||
}
|
||||
|
||||
// Get returns the current value of a GPIO pin when the pin is configured as an
|
||||
// input.
|
||||
func (p Pin) Get() bool {
|
||||
// See this document for details
|
||||
// https://www.espressif.com/sites/default/files/documentation/esp8266-technical_reference_en.pdf
|
||||
|
||||
return esp.GPIO.GPIO_IN.Get()&(1<<p) != 0
|
||||
}
|
||||
|
||||
// Set sets the output value of this pin to high (true) or low (false).
|
||||
func (p Pin) Set(value bool) {
|
||||
if value {
|
||||
|
||||
@@ -123,7 +123,7 @@ func (spi SPI) Configure(config SPIConfig) error {
|
||||
|
||||
// set default frequency
|
||||
if config.Frequency == 0 {
|
||||
config.Frequency = 4000000
|
||||
config.Frequency = 4000000 // 4MHz
|
||||
}
|
||||
|
||||
// div = (SPI_CFG(dev)->f_sys / (2 * frequency)) - 1;
|
||||
|
||||
@@ -172,7 +172,8 @@ func (p Pin) Get() bool {
|
||||
var pinCallbacks [32]func(Pin)
|
||||
|
||||
// SetInterrupt sets an interrupt to be executed when a particular pin changes
|
||||
// state.
|
||||
// state. The pin should already be configured as an input, including a pull up
|
||||
// or down if no external pull is provided.
|
||||
//
|
||||
// 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).
|
||||
@@ -442,7 +443,7 @@ func (spi SPI) Configure(config SPIConfig) error {
|
||||
|
||||
// Set default frequency.
|
||||
if config.Frequency == 0 {
|
||||
config.Frequency = 500000
|
||||
config.Frequency = 4000000 // 4MHz
|
||||
}
|
||||
|
||||
baudr := CPUFrequency() / config.Frequency
|
||||
|
||||
@@ -0,0 +1,881 @@
|
||||
// +build mimxrt1062
|
||||
|
||||
package machine
|
||||
|
||||
import (
|
||||
"device/nxp"
|
||||
"math/bits"
|
||||
"runtime/interrupt"
|
||||
"runtime/volatile"
|
||||
)
|
||||
|
||||
// Peripheral abstraction layer for the MIMXRT1062
|
||||
|
||||
func CPUFrequency() uint32 {
|
||||
return 600000000
|
||||
}
|
||||
|
||||
type PinMode uint8
|
||||
|
||||
const (
|
||||
// GPIO
|
||||
PinInput PinMode = iota
|
||||
PinInputPullUp
|
||||
PinInputPullDown
|
||||
PinOutput
|
||||
PinOutputOpenDrain
|
||||
PinDisable
|
||||
|
||||
// ADC
|
||||
PinInputAnalog
|
||||
|
||||
// UART
|
||||
PinModeUARTTX
|
||||
PinModeUARTRX
|
||||
|
||||
// SPI
|
||||
PinModeSPISDI
|
||||
PinModeSPISDO
|
||||
PinModeSPICLK
|
||||
PinModeSPICS
|
||||
|
||||
// I2C
|
||||
PinModeI2CSDA
|
||||
PinModeI2CSCL
|
||||
)
|
||||
|
||||
type PinChange uint8
|
||||
|
||||
const (
|
||||
PinLow PinChange = iota
|
||||
PinHigh
|
||||
PinRising
|
||||
PinFalling
|
||||
PinToggle
|
||||
)
|
||||
|
||||
// pinJumpTable represents a function lookup table for all 128 GPIO pins.
|
||||
//
|
||||
// There are 4 GPIO ports (A-D) and 32 pins (0-31) on each port. The uint8 value
|
||||
// of a Pin is used as table index. The number of pins with a defined (non-nil)
|
||||
// function is recorded in the uint8 field numDefined.
|
||||
type pinJumpTable struct {
|
||||
lut [4 * 32]func(Pin)
|
||||
numDefined uint8
|
||||
}
|
||||
|
||||
// pinISR stores the interrupt callbacks for GPIO pins, and pinInterrupt holds
|
||||
// an interrupt service routine that dispatches the interrupt callbacks.
|
||||
var (
|
||||
pinISR pinJumpTable
|
||||
pinInterrupt *interrupt.Interrupt
|
||||
)
|
||||
|
||||
// From the i.MXRT1062 Processor Reference Manual (Chapter 12 - GPIO):
|
||||
//
|
||||
// | High-speed GPIOs exist in this device:
|
||||
// | - GPIO1-5 are standard-speed GPIOs that run off the IPG_CLK_ROOT, while
|
||||
// | GPIO6-9 are high-speed GPIOs that run at the AHB_CLK_ROOT frequency.
|
||||
// | See the table "System Clocks, Gating, and Override" in CCM chapter.
|
||||
// | - Regular GPIO and high speed GPIO are paired (GPIO1 and GPIO6 share the
|
||||
// | same pins, GPIO2 and GPIO7 share, etc). The IOMUXC_GPR_GPR26-29
|
||||
// | registers are used to determine if the regular or high-speed GPIO
|
||||
// | module is used for the GPIO pins on a given port.
|
||||
//
|
||||
// Therefore, we do not even use GPIO1-5 and instead use their high-speed
|
||||
// partner for all pins. This is configured at startup in the runtime package
|
||||
// (func initPins() in `runtime_mimxrt1062.go`).
|
||||
// We cannot declare 32 pins for all available ports (GPIO1-9) anyway, since Pin
|
||||
// is only uint8, and 9*32=288 > 256, so something has to be sacrificed.
|
||||
|
||||
const (
|
||||
portA Pin = iota * 32 // GPIO1(6)
|
||||
portB // GPIO2(7)
|
||||
portC // GPIO3(8)
|
||||
portD // GPIO4(9)
|
||||
)
|
||||
|
||||
const (
|
||||
// [Pad]: Alt Func 0 Alt Func 1 Alt Func 2 Alt Func 3 Alt Func 4 Alt Func 5 Alt Func 6 Alt Func 7 Alt Func 8 Alt Func 9
|
||||
// ---------- --------------- --------------- ------------------- -------------------- -------------------- ----------- -------------------- -------------------- --------------------- ----------------
|
||||
PA0 = portA + 0 // [AD_B0_00]: FLEXPWM2_PWMA03 XBAR1_INOUT14 REF_CLK_32K USB_OTG2_ID LPI2C1_SCLS GPIO1_IO00 USDHC1_RESET_B LPSPI3_SCK ~ ~
|
||||
PA1 = portA + 1 // [AD_B0_01]: FLEXPWM2_PWMB03 XBAR1_INOUT15 REF_CLK_24M USB_OTG1_ID LPI2C1_SDAS GPIO1_IO01 EWM_OUT_B LPSPI3_SDO ~ ~
|
||||
PA2 = portA + 2 // [AD_B0_02]: FLEXCAN2_TX XBAR1_INOUT16 LPUART6_TX USB_OTG1_PWR FLEXPWM1_PWMX00 GPIO1_IO02 LPI2C1_HREQ LPSPI3_SDI ~ ~
|
||||
PA3 = portA + 3 // [AD_B0_03]: FLEXCAN2_RX XBAR1_INOUT17 LPUART6_RX USB_OTG1_OC FLEXPWM1_PWMX01 GPIO1_IO03 REF_CLK_24M LPSPI3_PCS0 ~ ~
|
||||
PA4 = portA + 4 // [AD_B0_04]: SRC_BOOT_MODE00 MQS_RIGHT ENET_TX_DATA03 SAI2_TX_SYNC CSI_DATA09 GPIO1_IO04 PIT_TRIGGER00 LPSPI3_PCS1 ~ ~
|
||||
PA5 = portA + 5 // [AD_B0_05]: SRC_BOOT_MODE01 MQS_LEFT ENET_TX_DATA02 SAI2_TX_BCLK CSI_DATA08 GPIO1_IO05 XBAR1_INOUT17 LPSPI3_PCS2 ~ ~
|
||||
PA6 = portA + 6 // [AD_B0_06]: JTAG_TMS GPT2_COMPARE1 ENET_RX_CLK SAI2_RX_BCLK CSI_DATA07 GPIO1_IO06 XBAR1_INOUT18 LPSPI3_PCS3 ~ ~
|
||||
PA7 = portA + 7 // [AD_B0_07]: JTAG_TCK GPT2_COMPARE2 ENET_TX_ER SAI2_RX_SYNC CSI_DATA06 GPIO1_IO07 XBAR1_INOUT19 ENET_1588_EVENT3_OUT ~ ~
|
||||
PA8 = portA + 8 // [AD_B0_08]: JTAG_MOD GPT2_COMPARE3 ENET_RX_DATA03 SAI2_RX_DATA CSI_DATA05 GPIO1_IO08 XBAR1_IN20 ENET_1588_EVENT3_IN ~ ~
|
||||
PA9 = portA + 9 // [AD_B0_09]: JTAG_TDI FLEXPWM2_PWMA03 ENET_RX_DATA02 SAI2_TX_DATA CSI_DATA04 GPIO1_IO09 XBAR1_IN21 GPT2_CLK SEMC_DQS4 ~
|
||||
PA10 = portA + 10 // [AD_B0_10]: JTAG_TDO FLEXPWM1_PWMA03 ENET_CRS SAI2_MCLK CSI_DATA03 GPIO1_IO10 XBAR1_IN22 ENET_1588_EVENT0_OUT FLEXCAN3_TX ARM_TRACE_SWO
|
||||
PA11 = portA + 11 // [AD_B0_11]: JTAG_TRSTB FLEXPWM1_PWMB03 ENET_COL WDOG1_WDOG_B CSI_DATA02 GPIO1_IO11 XBAR1_IN23 ENET_1588_EVENT0_IN FLEXCAN3_RX SEMC_CLK6
|
||||
PA12 = portA + 12 // [AD_B0_12]: LPI2C4_SCL CCM_PMIC_READY LPUART1_TX WDOG2_WDOG_B FLEXPWM1_PWMX02 GPIO1_IO12 ENET_1588_EVENT1_OUT NMI_GLUE_NMI ~ ~
|
||||
PA13 = portA + 13 // [AD_B0_13]: LPI2C4_SDA GPT1_CLK LPUART1_RX EWM_OUT_B FLEXPWM1_PWMX03 GPIO1_IO13 ENET_1588_EVENT1_IN REF_CLK_24M ~ ~
|
||||
PA14 = portA + 14 // [AD_B0_14]: USB_OTG2_OC XBAR1_IN24 LPUART1_CTS_B ENET_1588_EVENT0_OUT CSI_VSYNC GPIO1_IO14 FLEXCAN2_TX FLEXCAN3_TX ~ ~
|
||||
PA15 = portA + 15 // [AD_B0_15]: USB_OTG2_PWR XBAR1_IN25 LPUART1_RTS_B ENET_1588_EVENT0_IN CSI_HSYNC GPIO1_IO15 FLEXCAN2_RX WDOG1_WDOG_RST_B_DEB FLEXCAN3_RX ~
|
||||
PA16 = portA + 16 // [AD_B1_00]: USB_OTG2_ID QTIMER3_TIMER0 LPUART2_CTS_B LPI2C1_SCL WDOG1_B GPIO1_IO16 USDHC1_WP KPP_ROW07 ENET2_1588_EVENT0_OUT FLEXIO3_FLEXIO00
|
||||
PA17 = portA + 17 // [AD_B1_01]: USB_OTG1_PWR QTIMER3_TIMER1 LPUART2_RTS_B LPI2C1_SDA CCM_PMIC_READY GPIO1_IO17 USDHC1_VSELECT KPP_COL07 ENET2_1588_EVENT0_IN FLEXIO3_FLEXIO01
|
||||
PA18 = portA + 18 // [AD_B1_02]: USB_OTG1_ID QTIMER3_TIMER2 LPUART2_TX SPDIF_OUT ENET_1588_EVENT2_OUT GPIO1_IO18 USDHC1_CD_B KPP_ROW06 GPT2_CLK FLEXIO3_FLEXIO02
|
||||
PA19 = portA + 19 // [AD_B1_03]: USB_OTG1_OC QTIMER3_TIMER3 LPUART2_RX SPDIF_IN ENET_1588_EVENT2_IN GPIO1_IO19 USDHC2_CD_B KPP_COL06 GPT2_CAPTURE1 FLEXIO3_FLEXIO03
|
||||
PA20 = portA + 20 // [AD_B1_04]: FLEXSPIB_DATA03 ENET_MDC LPUART3_CTS_B SPDIF_SR_CLK CSI_PIXCLK GPIO1_IO20 USDHC2_DATA0 KPP_ROW05 GPT2_CAPTURE2 FLEXIO3_FLEXIO04
|
||||
PA21 = portA + 21 // [AD_B1_05]: FLEXSPIB_DATA02 ENET_MDIO LPUART3_RTS_B SPDIF_OUT CSI_MCLK GPIO1_IO21 USDHC2_DATA1 KPP_COL05 GPT2_COMPARE1 FLEXIO3_FLEXIO05
|
||||
PA22 = portA + 22 // [AD_B1_06]: FLEXSPIB_DATA01 LPI2C3_SDA LPUART3_TX SPDIF_LOCK CSI_VSYNC GPIO1_IO22 USDHC2_DATA2 KPP_ROW04 GPT2_COMPARE2 FLEXIO3_FLEXIO06
|
||||
PA23 = portA + 23 // [AD_B1_07]: FLEXSPIB_DATA00 LPI2C3_SCL LPUART3_RX SPDIF_EXT_CLK CSI_HSYNC GPIO1_IO23 USDHC2_DATA3 KPP_COL04 GPT2_COMPARE3 FLEXIO3_FLEXIO07
|
||||
PA24 = portA + 24 // [AD_B1_08]: FLEXSPIA_SS1_B FLEXPWM4_PWMA00 FLEXCAN1_TX CCM_PMIC_READY CSI_DATA09 GPIO1_IO24 USDHC2_CMD KPP_ROW03 FLEXIO3_FLEXIO08 ~
|
||||
PA25 = portA + 25 // [AD_B1_09]: FLEXSPIA_DQS FLEXPWM4_PWMA01 FLEXCAN1_RX SAI1_MCLK CSI_DATA08 GPIO1_IO25 USDHC2_CLK KPP_COL03 FLEXIO3_FLEXIO09 ~
|
||||
PA26 = portA + 26 // [AD_B1_10]: FLEXSPIA_DATA03 WDOG1_B LPUART8_TX SAI1_RX_SYNC CSI_DATA07 GPIO1_IO26 USDHC2_WP KPP_ROW02 ENET2_1588_EVENT1_OUT FLEXIO3_FLEXIO10
|
||||
PA27 = portA + 27 // [AD_B1_11]: FLEXSPIA_DATA02 EWM_OUT_B LPUART8_RX SAI1_RX_BCLK CSI_DATA06 GPIO1_IO27 USDHC2_RESET_B KPP_COL02 ENET2_1588_EVENT1_IN FLEXIO3_FLEXIO11
|
||||
PA28 = portA + 28 // [AD_B1_12]: FLEXSPIA_DATA01 ACMP_OUT00 LPSPI3_PCS0 SAI1_RX_DATA00 CSI_DATA05 GPIO1_IO28 USDHC2_DATA4 KPP_ROW01 ENET2_1588_EVENT2_OUT FLEXIO3_FLEXIO12
|
||||
PA29 = portA + 29 // [AD_B1_13]: FLEXSPIA_DATA00 ACMP_OUT01 LPSPI3_SDI SAI1_TX_DATA00 CSI_DATA04 GPIO1_IO29 USDHC2_DATA5 KPP_COL01 ENET2_1588_EVENT2_IN FLEXIO3_FLEXIO13
|
||||
PA30 = portA + 30 // [AD_B1_14]: FLEXSPIA_SCLK ACMP_OUT02 LPSPI3_SDO SAI1_TX_BCLK CSI_DATA03 GPIO1_IO30 USDHC2_DATA6 KPP_ROW00 ENET2_1588_EVENT3_OUT FLEXIO3_FLEXIO14
|
||||
PA31 = portA + 31 // [AD_B1_15]: FLEXSPIA_SS0_B ACMP_OUT03 LPSPI3_SCK SAI1_TX_SYNC CSI_DATA02 GPIO1_IO31 USDHC2_DATA7 KPP_COL00 ENET2_1588_EVENT3_IN FLEXIO3_FLEXIO15
|
||||
|
||||
PB0 = portB + 0 // [B0_00]: LCD_CLK QTIMER1_TIMER0 MQS_RIGHT LPSPI4_PCS0 FLEXIO2_FLEXIO00 GPIO2_IO00 SEMC_CSX01 ENET2_MDC ~ ~
|
||||
PB1 = portB + 1 // [B0_01]: LCD_ENABLE QTIMER1_TIMER1 MQS_LEFT LPSPI4_SDI FLEXIO2_FLEXIO01 GPIO2_IO01 SEMC_CSX02 ENET2_MDIO ~ ~
|
||||
PB2 = portB + 2 // [B0_02]: LCD_HSYNC QTIMER1_TIMER2 FLEXCAN1_TX LPSPI4_SDO FLEXIO2_FLEXIO02 GPIO2_IO02 SEMC_CSX03 ENET2_1588_EVENT0_OUT ~ ~
|
||||
PB3 = portB + 3 // [B0_03]: LCD_VSYNC QTIMER2_TIMER0 FLEXCAN1_RX LPSPI4_SCK FLEXIO2_FLEXIO03 GPIO2_IO03 WDOG2_RESET_B_DEB ENET2_1588_EVENT0_IN ~ ~
|
||||
PB4 = portB + 4 // [B0_04]: LCD_DATA00 QTIMER2_TIMER1 LPI2C2_SCL ARM_TRACE0 FLEXIO2_FLEXIO04 GPIO2_IO04 SRC_BOOT_CFG00 ENET2_TDATA03 ~ ~
|
||||
PB5 = portB + 5 // [B0_05]: LCD_DATA01 QTIMER2_TIMER2 LPI2C2_SDA ARM_TRACE1 FLEXIO2_FLEXIO05 GPIO2_IO05 SRC_BOOT_CFG01 ENET2_TDATA02 ~ ~
|
||||
PB6 = portB + 6 // [B0_06]: LCD_DATA02 QTIMER3_TIMER0 FLEXPWM2_PWMA00 ARM_TRACE2 FLEXIO2_FLEXIO06 GPIO2_IO06 SRC_BOOT_CFG02 ENET2_RX_CLK ~ ~
|
||||
PB7 = portB + 7 // [B0_07]: LCD_DATA03 QTIMER3_TIMER1 FLEXPWM2_PWMB00 ARM_TRACE3 FLEXIO2_FLEXIO07 GPIO2_IO07 SRC_BOOT_CFG03 ENET2_TX_ER ~ ~
|
||||
PB8 = portB + 8 // [B0_08]: LCD_DATA04 QTIMER3_TIMER2 FLEXPWM2_PWMA01 LPUART3_TX FLEXIO2_FLEXIO08 GPIO2_IO08 SRC_BOOT_CFG04 ENET2_RDATA03 ~ ~
|
||||
PB9 = portB + 9 // [B0_09]: LCD_DATA05 QTIMER4_TIMER0 FLEXPWM2_PWMB01 LPUART3_RX FLEXIO2_FLEXIO09 GPIO2_IO09 SRC_BOOT_CFG05 ENET2_RDATA02 ~ ~
|
||||
PB10 = portB + 10 // [B0_10]: LCD_DATA06 QTIMER4_TIMER1 FLEXPWM2_PWMA02 SAI1_TX_DATA03 FLEXIO2_FLEXIO10 GPIO2_IO10 SRC_BOOT_CFG06 ENET2_CRS ~ ~
|
||||
PB11 = portB + 11 // [B0_11]: LCD_DATA07 QTIMER4_TIMER2 FLEXPWM2_PWMB02 SAI1_TX_DATA02 FLEXIO2_FLEXIO11 GPIO2_IO11 SRC_BOOT_CFG07 ENET2_COL ~ ~
|
||||
PB12 = portB + 12 // [B0_12]: LCD_DATA08 XBAR1_INOUT10 ARM_TRACE_CLK SAI1_TX_DATA01 FLEXIO2_FLEXIO12 GPIO2_IO12 SRC_BOOT_CFG08 ENET2_TDATA00 ~ ~
|
||||
PB13 = portB + 13 // [B0_13]: LCD_DATA09 XBAR1_INOUT11 ARM_TRACE_SWO SAI1_MCLK FLEXIO2_FLEXIO13 GPIO2_IO13 SRC_BOOT_CFG09 ENET2_TDATA01 ~ ~
|
||||
PB14 = portB + 14 // [B0_14]: LCD_DATA10 XBAR1_INOUT12 ARM_TXEV SAI1_RX_SYNC FLEXIO2_FLEXIO14 GPIO2_IO14 SRC_BOOT_CFG10 ENET2_TX_EN ~ ~
|
||||
PB15 = portB + 15 // [B0_15]: LCD_DATA11 XBAR1_INOUT13 ARM_RXEV SAI1_RX_BCLK FLEXIO2_FLEXIO15 GPIO2_IO15 SRC_BOOT_CFG11 ENET2_TX_CLK ENET2_REF_CLK2 ~
|
||||
PB16 = portB + 16 // [B1_00]: LCD_DATA12 XBAR1_INOUT14 LPUART4_TX SAI1_RX_DATA00 FLEXIO2_FLEXIO16 GPIO2_IO16 FLEXPWM1_PWMA03 ENET2_RX_ER FLEXIO3_FLEXIO16 ~
|
||||
PB17 = portB + 17 // [B1_01]: LCD_DATA13 XBAR1_INOUT15 LPUART4_RX SAI1_TX_DATA00 FLEXIO2_FLEXIO17 GPIO2_IO17 FLEXPWM1_PWMB03 ENET2_RDATA00 FLEXIO3_FLEXIO17 ~
|
||||
PB18 = portB + 18 // [B1_02]: LCD_DATA14 XBAR1_INOUT16 LPSPI4_PCS2 SAI1_TX_BCLK FLEXIO2_FLEXIO18 GPIO2_IO18 FLEXPWM2_PWMA03 ENET2_RDATA01 FLEXIO3_FLEXIO18 ~
|
||||
PB19 = portB + 19 // [B1_03]: LCD_DATA15 XBAR1_INOUT17 LPSPI4_PCS1 SAI1_TX_SYNC FLEXIO2_FLEXIO19 GPIO2_IO19 FLEXPWM2_PWMB03 ENET2_RX_EN FLEXIO3_FLEXIO19 ~
|
||||
PB20 = portB + 20 // [B1_04]: LCD_DATA16 LPSPI4_PCS0 CSI_DATA15 ENET_RX_DATA00 FLEXIO2_FLEXIO20 GPIO2_IO20 GPT1_CLK FLEXIO3_FLEXIO20 ~ ~
|
||||
PB21 = portB + 21 // [B1_05]: LCD_DATA17 LPSPI4_SDI CSI_DATA14 ENET_RX_DATA01 FLEXIO2_FLEXIO21 GPIO2_IO21 GPT1_CAPTURE1 FLEXIO3_FLEXIO21 ~ ~
|
||||
PB22 = portB + 22 // [B1_06]: LCD_DATA18 LPSPI4_SDO CSI_DATA13 ENET_RX_EN FLEXIO2_FLEXIO22 GPIO2_IO22 GPT1_CAPTURE2 FLEXIO3_FLEXIO22 ~ ~
|
||||
PB23 = portB + 23 // [B1_07]: LCD_DATA19 LPSPI4_SCK CSI_DATA12 ENET_TX_DATA00 FLEXIO2_FLEXIO23 GPIO2_IO23 GPT1_COMPARE1 FLEXIO3_FLEXIO23 ~ ~
|
||||
PB24 = portB + 24 // [B1_08]: LCD_DATA20 QTIMER1_TIMER3 CSI_DATA11 ENET_TX_DATA01 FLEXIO2_FLEXIO24 GPIO2_IO24 FLEXCAN2_TX GPT1_COMPARE2 FLEXIO3_FLEXIO24 ~
|
||||
PB25 = portB + 25 // [B1_09]: LCD_DATA21 QTIMER2_TIMER3 CSI_DATA10 ENET_TX_EN FLEXIO2_FLEXIO25 GPIO2_IO25 FLEXCAN2_RX GPT1_COMPARE3 FLEXIO3_FLEXIO25 ~
|
||||
PB26 = portB + 26 // [B1_10]: LCD_DATA22 QTIMER3_TIMER3 CSI_DATA00 ENET_TX_CLK FLEXIO2_FLEXIO26 GPIO2_IO26 ENET_REF_CLK FLEXIO3_FLEXIO26 ~ ~
|
||||
PB27 = portB + 27 // [B1_11]: LCD_DATA23 QTIMER4_TIMER3 CSI_DATA01 ENET_RX_ER FLEXIO2_FLEXIO27 GPIO2_IO27 LPSPI4_PCS3 FLEXIO3_FLEXIO27 ~ ~
|
||||
PB28 = portB + 28 // [B1_12]: LPUART5_TX CSI_PIXCLK ENET_1588_EVENT0_IN FLEXIO2_FLEXIO28 GPIO2_IO28 USDHC1_CD_B FLEXIO3_FLEXIO28 ~ ~ ~
|
||||
PB29 = portB + 29 // [B1_13]: WDOG1_B LPUART5_RX CSI_VSYNC ENET_1588_EVENT0_OUT FLEXIO2_FLEXIO29 GPIO2_IO29 USDHC1_WP SEMC_DQS4 FLEXIO3_FLEXIO29 ~
|
||||
PB30 = portB + 30 // [B1_14]: ENET_MDC FLEXPWM4_PWMA02 CSI_HSYNC XBAR1_IN02 FLEXIO2_FLEXIO30 GPIO2_IO30 USDHC1_VSELECT ENET2_TDATA00 FLEXIO3_FLEXIO30 ~
|
||||
PB31 = portB + 31 // [B1_15]: ENET_MDIO FLEXPWM4_PWMA03 CSI_MCLK XBAR1_IN03 FLEXIO2_FLEXIO31 GPIO2_IO31 USDHC1_RESET_B ENET2_TDATA01 FLEXIO3_FLEXIO31 ~
|
||||
|
||||
PC0 = portC + 0 // [SD_B1_00]: USDHC2_DATA3 FLEXSPIB_DATA03 FLEXPWM1_PWMA03 SAI1_TX_DATA03 LPUART4_TX GPIO3_IO00 SAI3_RX_DATA ~ ~ ~
|
||||
PC1 = portC + 1 // [SD_B1_01]: USDHC2_DATA2 FLEXSPIB_DATA02 FLEXPWM1_PWMB03 SAI1_TX_DATA02 LPUART4_RX GPIO3_IO01 SAI3_TX_DATA ~ ~ ~
|
||||
PC2 = portC + 2 // [SD_B1_02]: USDHC2_DATA1 FLEXSPIB_DATA01 FLEXPWM2_PWMA03 SAI1_TX_DATA01 FLEXCAN1_TX GPIO3_IO02 CCM_WAIT SAI3_TX_SYNC ~ ~
|
||||
PC3 = portC + 3 // [SD_B1_03]: USDHC2_DATA0 FLEXSPIB_DATA00 FLEXPWM2_PWMB03 SAI1_MCLK FLEXCAN1_RX GPIO3_IO03 CCM_PMIC_READY SAI3_TX_BCLK ~ ~
|
||||
PC4 = portC + 4 // [SD_B1_04]: USDHC2_CLK FLEXSPIB_SCLK LPI2C1_SCL SAI1_RX_SYNC FLEXSPIA_SS1_B GPIO3_IO04 CCM_STOP SAI3_MCLK ~ ~
|
||||
PC5 = portC + 5 // [SD_B1_05]: USDHC2_CMD FLEXSPIA_DQS LPI2C1_SDA SAI1_RX_BCLK FLEXSPIB_SS0_B GPIO3_IO05 SAI3_RX_SYNC ~ ~ ~
|
||||
PC6 = portC + 6 // [SD_B1_06]: USDHC2_RESET_B FLEXSPIA_SS0_B LPUART7_CTS_B SAI1_RX_DATA00 LPSPI2_PCS0 GPIO3_IO06 SAI3_RX_BCLK ~ ~ ~
|
||||
PC7 = portC + 7 // [SD_B1_07]: SEMC_CSX01 FLEXSPIA_SCLK LPUART7_RTS_B SAI1_TX_DATA00 LPSPI2_SCK GPIO3_IO07 ~ ~ ~ ~
|
||||
PC8 = portC + 8 // [SD_B1_08]: USDHC2_DATA4 FLEXSPIA_DATA00 LPUART7_TX SAI1_TX_BCLK LPSPI2_SD0 GPIO3_IO08 SEMC_CSX02 ~ ~ ~
|
||||
PC9 = portC + 9 // [SD_B1_09]: USDHC2_DATA5 FLEXSPIA_DATA01 LPUART7_RX SAI1_TX_SYNC LPSPI2_SDI GPIO3_IO09 ~ ~ ~ ~
|
||||
PC10 = portC + 10 // [SD_B1_10]: USDHC2_DATA6 FLEXSPIA_DATA02 LPUART2_RX LPI2C2_SDA LPSPI2_PCS2 GPIO3_IO10 ~ ~ ~ ~
|
||||
PC11 = portC + 11 // [SD_B1_11]: USDHC2_DATA7 FLEXSPIA_DATA03 LPUART2_TX LPI2C2_SCL LPSPI2_PCS3 GPIO3_IO11 ~ ~ ~ ~
|
||||
PC12 = portC + 12 // [SD_B0_00]: USDHC1_CMD FLEXPWM1_PWMA00 LPI2C3_SCL XBAR1_INOUT04 LPSPI1_SCK GPIO3_IO12 FLEXSPIA_SS1_B ENET2_TX_EN SEMC_DQS4 ~
|
||||
PC13 = portC + 13 // [SD_B0_01]: USDHC1_CLK FLEXPWM1_PWMB00 LPI2C3_SDA XBAR1_INOUT05 LPSPI1_PCS0 GPIO3_IO13 FLEXSPIB_SS1_B ENET2_TX_CLK ENET2_REF_CLK2 ~
|
||||
PC14 = portC + 14 // [SD_B0_02]: USDHC1_DATA0 FLEXPWM1_PWMA01 LPUART8_CTS_B XBAR1_INOUT06 LPSPI1_SDO GPIO3_IO14 ENET2_RX_ER SEMC_CLK5 ~ ~
|
||||
PC15 = portC + 15 // [SD_B0_03]: USDHC1_DATA1 FLEXPWM1_PWMB01 LPUART8_RTS_B XBAR1_INOUT07 LPSPI1_SDI GPIO3_IO15 ENET2_RDATA00 SEMC_CLK6 ~ ~
|
||||
PC16 = portC + 16 // [SD_B0_04]: USDHC1_DATA2 FLEXPWM1_PWMA02 LPUART8_TX XBAR1_INOUT08 FLEXSPIB_SS0_B GPIO3_IO16 CCM_CLKO1 ENET2_RDATA01 ~ ~
|
||||
PC17 = portC + 17 // [SD_B0_05]: USDHC1_DATA3 FLEXPWM1_PWMB02 LPUART8_RX XBAR1_INOUT09 FLEXSPIB_DQS GPIO3_IO17 CCM_CLKO2 ENET2_RX_EN ~ ~
|
||||
PC18 = portC + 18 // [EMC_32]: SEMC_DATA10 FLEXPWM3_PWMB01 LPUART7_RX CCM_PMIC_RDY CSI_DATA21 GPIO3_IO18 ENET2_TX_EN ~ ~ ~
|
||||
PC19 = portC + 19 // [EMC_33]: SEMC_DATA11 FLEXPWM3_PWMA02 USDHC1_RESET_B SAI3_RX_DATA CSI_DATA20 GPIO3_IO19 ENET2_TX_CLK ENET2_REF_CLK2 ~ ~
|
||||
PC20 = portC + 20 // [EMC_34]: SEMC_DATA12 FLEXPWM3_PWMB02 USDHC1_VSELECT SAI3_RX_SYNC CSI_DATA19 GPIO3_IO20 ENET2_RX_ER ~ ~ ~
|
||||
PC21 = portC + 21 // [EMC_35]: SEMC_DATA13 XBAR1_INOUT18 GPT1_COMPARE1 SAI3_RX_BCLK CSI_DATA18 GPIO3_IO21 USDHC1_CD_B ENET2_RDATA00 ~ ~
|
||||
PC22 = portC + 22 // [EMC_36]: SEMC_DATA14 XBAR1_IN22 GPT1_COMPARE2 SAI3_TX_DATA CSI_DATA17 GPIO3_IO22 USDHC1_WP ENET2_RDATA01 FLEXCAN3_TX ~
|
||||
PC23 = portC + 23 // [EMC_37]: SEMC_DATA15 XBAR1_IN23 GPT1_COMPARE3 SAI3_MCLK CSI_DATA16 GPIO3_IO23 USDHC2_WP ENET2_RX_EN FLEXCAN3_RX ~
|
||||
PC24 = portC + 24 // [EMC_38]: SEMC_DM01 FLEXPWM1_PWMA03 LPUART8_TX SAI3_TX_BCLK CSI_FIELD GPIO3_IO24 USDHC2_VSELECT ENET2_MDC ~ ~
|
||||
PC25 = portC + 25 // [EMC_39]: SEMC_DQS FLEXPWM1_PWMB03 LPUART8_RX SAI3_TX_SYNC WDOG1_WDOG_B GPIO3_IO25 USDHC2_CD_B ENET2_MDIO SEMC_DQS4 ~
|
||||
PC26 = portC + 26 // [EMC_40]: SEMC_RDY GPT2_CAPTURE2 LPSPI1_PCS2 USB_OTG2_OC ENET_MDC GPIO3_IO26 USDHC2_RESET_B SEMC_CLK5 ~ ~
|
||||
PC27 = portC + 27 // [EMC_41]: SEMC_CSX00 GPT2_CAPTURE1 LPSPI1_PCS3 USB_OTG2_PWR ENET_MDIO GPIO3_IO27 USDHC1_VSELECT ~ ~ ~
|
||||
_ = portC + 28 //
|
||||
_ = portC + 29 //
|
||||
_ = portC + 30 //
|
||||
_ = portC + 31 //
|
||||
|
||||
PD0 = portD + 0 // [EMC_00]: SEMC_DATA00 FLEXPWM4_PWMA00 LPSPI2_SCK XBAR1_XBAR_IN02 FLEXIO1_FLEXIO00 GPIO4_IO00 ~ ~ ~ ~
|
||||
PD1 = portD + 1 // [EMC_01]: SEMC_DATA01 FLEXPWM4_PWMB00 LPSPI2_PCS0 XBAR1_IN03 FLEXIO1_FLEXIO01 GPIO4_IO01 ~ ~ ~ ~
|
||||
PD2 = portD + 2 // [EMC_02]: SEMC_DATA02 FLEXPWM4_PWMA01 LPSPI2_SDO XBAR1_INOUT04 FLEXIO1_FLEXIO02 GPIO4_IO02 ~ ~ ~ ~
|
||||
PD3 = portD + 3 // [EMC_03]: SEMC_DATA03 FLEXPWM4_PWMB01 LPSPI2_SDI XBAR1_INOUT05 FLEXIO1_FLEXIO03 GPIO4_IO03 ~ ~ ~ ~
|
||||
PD4 = portD + 4 // [EMC_04]: SEMC_DATA04 FLEXPWM4_PWMA02 SAI2_TX_DATA XBAR1_INOUT06 FLEXIO1_FLEXIO04 GPIO4_IO04 ~ ~ ~ ~
|
||||
PD5 = portD + 5 // [EMC_05]: SEMC_DATA05 FLEXPWM4_PWMB02 SAI2_TX_SYNC XBAR1_INOUT07 FLEXIO1_FLEXIO05 GPIO4_IO05 ~ ~ ~ ~
|
||||
PD6 = portD + 6 // [EMC_06]: SEMC_DATA06 FLEXPWM2_PWMA00 SAI2_TX_BCLK XBAR1_INOUT08 FLEXIO1_FLEXIO06 GPIO4_IO06 ~ ~ ~ ~
|
||||
PD7 = portD + 7 // [EMC_07]: SEMC_DATA07 FLEXPWM2_PWMB00 SAI2_MCLK XBAR1_INOUT09 FLEXIO1_FLEXIO07 GPIO4_IO07 ~ ~ ~ ~
|
||||
PD8 = portD + 8 // [EMC_08]: SEMC_DM00 FLEXPWM2_PWMA01 SAI2_RX_DATA XBAR1_INOUT17 FLEXIO1_FLEXIO08 GPIO4_IO08 ~ ~ ~ ~
|
||||
PD9 = portD + 9 // [EMC_09]: SEMC_ADDR00 FLEXPWM2_PWMB01 SAI2_RX_SYNC FLEXCAN2_TX FLEXIO1_FLEXIO09 GPIO4_IO09 FLEXSPI2_B_SS1_B ~ ~ ~
|
||||
PD10 = portD + 10 // [EMC_10]: SEMC_ADDR01 FLEXPWM2_PWMA02 SAI2_RX_BCLK FLEXCAN2_RX FLEXIO1_FLEXIO10 GPIO4_IO10 FLEXSPI2_B_SS0_B ~ ~ ~
|
||||
PD11 = portD + 11 // [EMC_11]: SEMC_ADDR02 FLEXPWM2_PWMB02 LPI2C4_SDA USDHC2_RESET_B FLEXIO1_FLEXIO11 GPIO4_IO11 FLEXSPI2_B_DQS ~ ~ ~
|
||||
PD12 = portD + 12 // [EMC_12]: SEMC_ADDR03 XBAR1_IN24 LPI2C4_SCL USDHC1_WP FLEXPWM1_PWMA03 GPIO4_IO12 FLEXSPI2_B_SCLK ~ ~ ~
|
||||
PD13 = portD + 13 // [EMC_13]: SEMC_ADDR04 XBAR1_IN25 LPUART3_TX MQS_RIGHT FLEXPWM1_PWMB03 GPIO4_IO13 FLEXSPI2_B_DATA00 ~ ~ ~
|
||||
PD14 = portD + 14 // [EMC_14]: SEMC_ADDR05 XBAR1_INOUT19 LPUART3_RX MQS_LEFT LPSPI2_PCS1 GPIO4_IO14 FLEXSPI2_B_DATA01 ~ ~ ~
|
||||
PD15 = portD + 15 // [EMC_15]: SEMC_ADDR06 XBAR1_IN20 LPUART3_CTS_B SPDIF_OUT QTIMER3_TIMER0 GPIO4_IO15 FLEXSPI2_B_DATA02 ~ ~ ~
|
||||
PD16 = portD + 16 // [EMC_16]: SEMC_ADDR07 XBAR1_IN21 LPUART3_RTS_B SPDIF_IN QTIMER3_TIMER1 GPIO4_IO16 FLEXSPI2_B_DATA03 ~ ~ ~
|
||||
PD17 = portD + 17 // [EMC_17]: SEMC_ADDR08 FLEXPWM4_PWMA03 LPUART4_CTS_B FLEXCAN1_TX QTIMER3_TIMER2 GPIO4_IO17 ~ ~ ~ ~
|
||||
PD18 = portD + 18 // [EMC_18]: SEMC_ADDR09 FLEXPWM4_PWMB03 LPUART4_RTS_B FLEXCAN1_RX QTIMER3_TIMER3 GPIO4_IO18 SNVS_VIO_5_CTL ~ ~ ~
|
||||
PD19 = portD + 19 // [EMC_19]: SEMC_ADDR11 FLEXPWM2_PWMA03 LPUART4_TX ENET_RDATA01 QTIMER2_TIMER0 GPIO4_IO19 SNVS_VIO_5 ~ ~ ~
|
||||
PD20 = portD + 20 // [EMC_20]: SEMC_ADDR12 FLEXPWM2_PWMB03 LPUART4_RX ENET_RDATA00 QTIMER2_TIMER1 GPIO4_IO20 ~ ~ ~ ~
|
||||
PD21 = portD + 21 // [EMC_21]: SEMC_BA0 FLEXPWM3_PWMA03 LPI2C3_SDA ENET_TDATA01 QTIMER2_TIMER2 GPIO4_IO21 ~ ~ ~ ~
|
||||
PD22 = portD + 22 // [EMC_22]: SEMC_BA1 FLEXPWM3_PWMB03 LPI2C3_SCL ENET_TDATA00 QTIMER2_TIMER3 GPIO4_IO22 FLEXSPI2_A_SS1_B ~ ~ ~
|
||||
PD23 = portD + 23 // [EMC_23]: SEMC_ADDR10 FLEXPWM1_PWMA00 LPUART5_TX ENET_RX_EN GPT1_CAPTURE2 GPIO4_IO23 FLEXSPI2_A_DQS ~ ~ ~
|
||||
PD24 = portD + 24 // [EMC_24]: SEMC_CAS FLEXPWM1_PWMB00 LPUART5_RX ENET_TX_EN GPT1_CAPTURE1 GPIO4_IO24 FLEXSPI2_A_SS0_B ~ ~ ~
|
||||
PD25 = portD + 25 // [EMC_25]: SEMC_RAS FLEXPWM1_PWMA01 LPUART6_TX ENET_TX_CLK ENET_REF_CLK GPIO4_IO25 FLEXSPI2_A_SCLK ~ ~ ~
|
||||
PD26 = portD + 26 // [EMC_26]: SEMC_CLK FLEXPWM1_PWMB01 LPUART6_RX ENET_RX_ER FLEXIO1_FLEXIO12 GPIO4_IO26 FLEXSPI2_A_DATA00 ~ ~ ~
|
||||
PD27 = portD + 27 // [EMC_27]: SEMC_CKE FLEXPWM1_PWMA02 LPUART5_RTS_B LPSPI1_SCK FLEXIO1_FLEXIO13 GPIO4_IO27 FLEXSPI2_A_DATA01 ~ ~ ~
|
||||
PD28 = portD + 28 // [EMC_28]: SEMC_WE FLEXPWM1_PWMB02 LPUART5_CTS_B LPSPI1_SDO FLEXIO1_FLEXIO14 GPIO4_IO28 FLEXSPI2_A_DATA02 ~ ~ ~
|
||||
PD29 = portD + 29 // [EMC_29]: SEMC_CS0 FLEXPWM3_PWMA00 LPUART6_RTS_B LPSPI1_SDI FLEXIO1_FLEXIO15 GPIO4_IO29 FLEXSPI2_A_DATA03 ~ ~ ~
|
||||
PD30 = portD + 30 // [EMC_30]: SEMC_DATA08 FLEXPWM3_PWMB00 LPUART6_CTS_B LPSPI1_PCS0 CSI_DATA23 GPIO4_IO30 ENET2_TDATA00 ~ ~ ~
|
||||
PD31 = portD + 31 // [EMC_31]: SEMC_DATA09 FLEXPWM3_PWMA01 LPUART7_TX LPSPI1_PCS1 CSI_DATA22 GPIO4_IO31 ENET2_TDATA01 ~ ~ ~
|
||||
)
|
||||
|
||||
func (p Pin) getPos() uint8 { return uint8(p % 32) }
|
||||
func (p Pin) getMask() uint32 { return uint32(1) << p.getPos() }
|
||||
func (p Pin) getPort() Pin { return Pin(p/32) * 32 }
|
||||
|
||||
// Configure sets the GPIO pad and pin properties, and selects the appropriate
|
||||
// alternate function, for a given Pin and PinConfig.
|
||||
func (p Pin) Configure(config PinConfig) {
|
||||
var (
|
||||
sre = uint32(0x01 << 0)
|
||||
dse = func(n uint32) uint32 { return (n & 0x07) << 3 }
|
||||
spd = func(n uint32) uint32 { return (n & 0x03) << 6 }
|
||||
ode = uint32(0x01 << 11)
|
||||
pke = uint32(0x01 << 12)
|
||||
pue = uint32(0x01 << 13)
|
||||
pup = func(n uint32) uint32 { return (n & 0x03) << 14 }
|
||||
hys = uint32(0x01 << 16)
|
||||
)
|
||||
|
||||
_, gpio := p.getGPIO() // use fast GPIO for all pins
|
||||
pad, mux := p.getPad()
|
||||
|
||||
// first configure the pad characteristics
|
||||
switch config.Mode {
|
||||
case PinInput:
|
||||
gpio.GDIR.ClearBits(p.getMask())
|
||||
pad.Set(dse(7))
|
||||
|
||||
case PinInputPullUp:
|
||||
gpio.GDIR.ClearBits(p.getMask())
|
||||
pad.Set(dse(7) | pke | pue | pup(3) | hys)
|
||||
|
||||
case PinInputPullDown:
|
||||
gpio.GDIR.ClearBits(p.getMask())
|
||||
pad.Set(dse(7) | pke | pue | hys)
|
||||
|
||||
case PinOutput:
|
||||
gpio.GDIR.SetBits(p.getMask())
|
||||
pad.Set(dse(7))
|
||||
|
||||
case PinOutputOpenDrain:
|
||||
gpio.GDIR.SetBits(p.getMask())
|
||||
pad.Set(dse(7) | ode)
|
||||
|
||||
case PinDisable:
|
||||
gpio.GDIR.ClearBits(p.getMask())
|
||||
pad.Set(dse(7) | hys)
|
||||
|
||||
case PinInputAnalog:
|
||||
gpio.GDIR.ClearBits(p.getMask())
|
||||
pad.Set(dse(7))
|
||||
|
||||
case PinModeUARTTX:
|
||||
pad.Set(sre | dse(3) | spd(3))
|
||||
|
||||
case PinModeUARTRX:
|
||||
pad.Set(dse(7) | pke | pue | pup(3) | hys)
|
||||
|
||||
case PinModeSPISDI:
|
||||
pad.Set(dse(7) | spd(2))
|
||||
|
||||
case PinModeSPISDO:
|
||||
pad.Set(dse(7) | spd(2))
|
||||
|
||||
case PinModeSPICLK:
|
||||
pad.Set(dse(7) | spd(2))
|
||||
|
||||
case PinModeSPICS:
|
||||
pad.Set(dse(7))
|
||||
|
||||
case PinModeI2CSDA, PinModeI2CSCL:
|
||||
pad.Set(ode | sre | dse(4) | spd(1) | pke | pue | pup(3))
|
||||
}
|
||||
|
||||
// then configure the alternate function mux
|
||||
mux.Set(p.getMuxMode(config))
|
||||
}
|
||||
|
||||
// Get returns the current value of a GPIO pin.
|
||||
func (p Pin) Get() bool {
|
||||
_, gpio := p.getGPIO() // use fast GPIO for all pins
|
||||
return gpio.PSR.HasBits(p.getMask())
|
||||
}
|
||||
|
||||
// Set changes the value of the GPIO pin. The pin must be configured as output.
|
||||
func (p Pin) Set(value bool) {
|
||||
_, gpio := p.getGPIO() // use fast GPIO for all pins
|
||||
if value {
|
||||
gpio.DR_SET.Set(p.getMask())
|
||||
} else {
|
||||
gpio.DR_CLEAR.Set(p.getMask())
|
||||
}
|
||||
}
|
||||
|
||||
// Toggle switches an output pin from low to high or from high to low.
|
||||
func (p Pin) Toggle() {
|
||||
_, gpio := p.getGPIO() // use fast GPIO for all pins
|
||||
gpio.DR_TOGGLE.Set(p.getMask())
|
||||
}
|
||||
|
||||
// dispatchInterrupt invokes the user-provided callback functions for external
|
||||
// interrupts generated on the high-speed GPIO pins.
|
||||
//
|
||||
// Unfortunately, all four high-speed GPIO ports (A-D) are connected to just a
|
||||
// single interrupt control line. Therefore, the interrupt status register (ISR)
|
||||
// must be checked in all four GPIO ports on every interrupt.
|
||||
func (jt *pinJumpTable) dispatchInterrupt(interrupt.Interrupt) {
|
||||
handle := func(gpio *nxp.GPIO_Type, port Pin) {
|
||||
if status := gpio.ISR.Get() & gpio.IMR.Get(); status != 0 {
|
||||
gpio.ISR.Set(status) // clear interrupt
|
||||
for status != 0 {
|
||||
p := Pin(bits.TrailingZeros32(status))
|
||||
i := Pin(port + p)
|
||||
jt.lut[i](i)
|
||||
status &^= 1 << p
|
||||
}
|
||||
}
|
||||
}
|
||||
if jt.numDefined > 0 {
|
||||
handle(nxp.GPIO6, portA)
|
||||
handle(nxp.GPIO7, portB)
|
||||
handle(nxp.GPIO8, portC)
|
||||
handle(nxp.GPIO9, portD)
|
||||
}
|
||||
}
|
||||
|
||||
// set associates a function with a given Pin in the receiver lookup table. If
|
||||
// the function is nil, the given Pin's associated function is removed.
|
||||
func (jt *pinJumpTable) set(pin Pin, fn func(Pin)) {
|
||||
if int(pin) < len(jt.lut) {
|
||||
if nil != fn {
|
||||
if nil == jt.lut[pin] {
|
||||
jt.numDefined++
|
||||
}
|
||||
jt.lut[pin] = fn
|
||||
} else {
|
||||
if nil != jt.lut[pin] {
|
||||
jt.numDefined--
|
||||
}
|
||||
jt.lut[pin] = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SetInterrupt sets an interrupt to be executed when a particular pin changes
|
||||
// state. The pin should already be configured as an input, including a pull up
|
||||
// or down if no external pull is provided.
|
||||
//
|
||||
// This call will replace a previously set callback on this pin. 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).
|
||||
func (p Pin) SetInterrupt(change PinChange, callback func(Pin)) error {
|
||||
_, gpio := p.getGPIO() // use fast GPIO for all pins
|
||||
mask := p.getMask()
|
||||
if nil != callback {
|
||||
switch change {
|
||||
case PinLow, PinHigh, PinRising, PinFalling:
|
||||
gpio.EDGE_SEL.ClearBits(mask)
|
||||
var reg *volatile.Register32
|
||||
var pos uint8
|
||||
if pos = p.getPos(); pos < 16 {
|
||||
reg = &gpio.ICR1 // ICR1 = pins 0-15
|
||||
} else {
|
||||
reg = &gpio.ICR2 // ICR2 = pins 16-31
|
||||
pos -= 16
|
||||
}
|
||||
reg.ReplaceBits(uint32(change), 0x3, pos*2)
|
||||
case PinToggle:
|
||||
gpio.EDGE_SEL.SetBits(mask)
|
||||
}
|
||||
pinISR.set(p, callback) // associate the callback with the pin
|
||||
gpio.ISR.Set(mask) // clear any pending interrupt (W1C)
|
||||
gpio.IMR.SetBits(mask) // enable external interrupt
|
||||
} else {
|
||||
pinISR.set(p, nil) // remove any associated callback from the pin
|
||||
gpio.ISR.Set(mask) // clear any pending interrupt (W1C)
|
||||
gpio.IMR.ClearBits(mask) // disable external interrupt
|
||||
}
|
||||
// enable or disable the interrupt based on number of defined callbacks
|
||||
if pinISR.numDefined > 0 {
|
||||
if nil == pinInterrupt {
|
||||
// create the Interrupt if it is not yet defined
|
||||
irq := interrupt.New(nxp.IRQ_GPIO6_7_8_9, pinISR.dispatchInterrupt)
|
||||
pinInterrupt = &irq
|
||||
pinInterrupt.Enable()
|
||||
}
|
||||
} else {
|
||||
if nil != pinInterrupt {
|
||||
// disable the interrupt if it is defined
|
||||
pinInterrupt.Disable()
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// getGPIO returns both the normal (IPG_CLK_ROOT) and high-speed (AHB_CLK_ROOT)
|
||||
// GPIO peripherals to which a given Pin is connected.
|
||||
//
|
||||
// Note that, currently, the device is configured to use high-speed GPIO for all
|
||||
// pins (GPIO6-9), so the first return value should not be used (GPIO1-4).
|
||||
// See the remarks and documentation reference in the comments preceding the
|
||||
// const Pin definitions above.
|
||||
func (p Pin) getGPIO() (norm *nxp.GPIO_Type, fast *nxp.GPIO_Type) {
|
||||
switch p.getPort() {
|
||||
case portA:
|
||||
return nxp.GPIO1, nxp.GPIO6
|
||||
case portB:
|
||||
return nxp.GPIO2, nxp.GPIO7
|
||||
case portC:
|
||||
return nxp.GPIO3, nxp.GPIO8
|
||||
case portD:
|
||||
return nxp.GPIO4, nxp.GPIO9
|
||||
default:
|
||||
panic("machine: unknown port")
|
||||
}
|
||||
}
|
||||
|
||||
// getPad returns both the pad and mux configration registers for a given Pin.
|
||||
func (p Pin) getPad() (pad *volatile.Register32, mux *volatile.Register32) {
|
||||
switch p.getPort() {
|
||||
case portA:
|
||||
switch p.getPos() {
|
||||
case 0:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_00, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_00
|
||||
case 1:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_01, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_01
|
||||
case 2:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_02, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_02
|
||||
case 3:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_03, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_03
|
||||
case 4:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_04, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_04
|
||||
case 5:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_05, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_05
|
||||
case 6:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_06, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_06
|
||||
case 7:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_07, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_07
|
||||
case 8:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_08, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_08
|
||||
case 9:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_09, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_09
|
||||
case 10:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_10, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_10
|
||||
case 11:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_11, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_11
|
||||
case 12:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_12, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_12
|
||||
case 13:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_13, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_13
|
||||
case 14:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_14, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_14
|
||||
case 15:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_15, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_15
|
||||
case 16:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_00, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_00
|
||||
case 17:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_01, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_01
|
||||
case 18:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_02, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_02
|
||||
case 19:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_03, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_03
|
||||
case 20:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_04, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_04
|
||||
case 21:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_05, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_05
|
||||
case 22:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_06, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_06
|
||||
case 23:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_07, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_07
|
||||
case 24:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_08, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_08
|
||||
case 25:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_09, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_09
|
||||
case 26:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_10, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_10
|
||||
case 27:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_11, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_11
|
||||
case 28:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_12, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_12
|
||||
case 29:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_13, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_13
|
||||
case 30:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_14, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_14
|
||||
case 31:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_15, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_15
|
||||
}
|
||||
case portB:
|
||||
switch p.getPos() {
|
||||
case 0:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_00, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_00
|
||||
case 1:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_01, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_01
|
||||
case 2:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_02, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_02
|
||||
case 3:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_03, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_03
|
||||
case 4:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_04, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_04
|
||||
case 5:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_05, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_05
|
||||
case 6:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_06, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_06
|
||||
case 7:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_07, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_07
|
||||
case 8:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_08, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_08
|
||||
case 9:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_09, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_09
|
||||
case 10:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_10, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_10
|
||||
case 11:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_11, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_11
|
||||
case 12:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_12, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_12
|
||||
case 13:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_13, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_13
|
||||
case 14:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_14, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_14
|
||||
case 15:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_15, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_15
|
||||
case 16:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_00, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_00
|
||||
case 17:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_01, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_01
|
||||
case 18:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_02, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_02
|
||||
case 19:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_03, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_03
|
||||
case 20:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_04, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_04
|
||||
case 21:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_05, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_05
|
||||
case 22:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_06, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_06
|
||||
case 23:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_07, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_07
|
||||
case 24:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_08, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_08
|
||||
case 25:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_09, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_09
|
||||
case 26:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_10, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_10
|
||||
case 27:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_11, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_11
|
||||
case 28:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_12, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_12
|
||||
case 29:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_13, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_13
|
||||
case 30:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_14, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_14
|
||||
case 31:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_15, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_15
|
||||
}
|
||||
case portC:
|
||||
switch p.getPos() {
|
||||
case 0:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_00, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_00
|
||||
case 1:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_01, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_01
|
||||
case 2:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_02, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_02
|
||||
case 3:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_03, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_03
|
||||
case 4:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_04, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_04
|
||||
case 5:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_05, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_05
|
||||
case 6:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_06, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_06
|
||||
case 7:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_07, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_07
|
||||
case 8:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_08, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_08
|
||||
case 9:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_09, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_09
|
||||
case 10:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_10, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_10
|
||||
case 11:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_11, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_11
|
||||
case 12:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B0_00, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B0_00
|
||||
case 13:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B0_01, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B0_01
|
||||
case 14:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B0_02, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B0_02
|
||||
case 15:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B0_03, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B0_03
|
||||
case 16:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B0_04, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B0_04
|
||||
case 17:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B0_05, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B0_05
|
||||
case 18:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_32, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_32
|
||||
case 19:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_33, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_33
|
||||
case 20:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_34, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_34
|
||||
case 21:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_35, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_35
|
||||
case 22:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_36, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_36
|
||||
case 23:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_37, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_37
|
||||
case 24:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_38, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_38
|
||||
case 25:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_39, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_39
|
||||
case 26:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_40, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_40
|
||||
case 27:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_41, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_41
|
||||
case 28, 29, 30, 31:
|
||||
}
|
||||
case portD:
|
||||
switch p.getPos() {
|
||||
case 0:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_00, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_00
|
||||
case 1:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_01, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_01
|
||||
case 2:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_02, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_02
|
||||
case 3:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_03, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_03
|
||||
case 4:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_04, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_04
|
||||
case 5:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_05, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_05
|
||||
case 6:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_06, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_06
|
||||
case 7:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_07, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_07
|
||||
case 8:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_08, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_08
|
||||
case 9:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_09, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_09
|
||||
case 10:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_10, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_10
|
||||
case 11:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_11, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_11
|
||||
case 12:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_12, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_12
|
||||
case 13:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_13, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_13
|
||||
case 14:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_14, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_14
|
||||
case 15:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_15, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_15
|
||||
case 16:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_16, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_16
|
||||
case 17:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_17, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_17
|
||||
case 18:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_18, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_18
|
||||
case 19:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_19, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_19
|
||||
case 20:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_20, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_20
|
||||
case 21:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_21, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_21
|
||||
case 22:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_22, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_22
|
||||
case 23:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_23, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_23
|
||||
case 24:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_24, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_24
|
||||
case 25:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_25, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_25
|
||||
case 26:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_26, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_26
|
||||
case 27:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_27, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_27
|
||||
case 28:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_28, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_28
|
||||
case 29:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_29, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_29
|
||||
case 30:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_30, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_30
|
||||
case 31:
|
||||
return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_31, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_31
|
||||
}
|
||||
}
|
||||
panic("machine: invalid pin")
|
||||
}
|
||||
|
||||
// muxSelect is yet another level of indirection required to connect pins in an
|
||||
// alternate function state to a desired peripheral (since more than one pin can
|
||||
// provide a given alternate function).
|
||||
//
|
||||
// Once a pin is configured with a given alternate function mode, the IOMUXC
|
||||
// device must then be configured to select which alternate function pin to
|
||||
// route to the desired peripheral.
|
||||
//
|
||||
// The reference manual refers to this functionality as a "Daisy Chain". The
|
||||
// associated docs are found in the i.MX RT1060 Processor Reference Manual:
|
||||
// "Chapter 11.3.3 Daisy chain - multi pads driving same module input pin"
|
||||
type muxSelect struct {
|
||||
mux uint8 // AF mux selection (NOT a Pin type)
|
||||
sel *volatile.Register32 // AF selection register
|
||||
}
|
||||
|
||||
// connect configures the IOMUXC controller to route a given pin with alternate
|
||||
// function to a desired peripheral (see godoc comments on type muxSelect).
|
||||
func (s muxSelect) connect() {
|
||||
s.sel.Set(uint32(s.mux))
|
||||
}
|
||||
|
||||
// getMuxMode acts as a callback from the `(Pin).Configure(PinMode)` routine to
|
||||
// determine the alternate function setting for a given Pin and PinConfig.
|
||||
// This value is used in the IOMUXC device's SW_MUX_CTL_PAD_GPIO_* registers.
|
||||
func (p Pin) getMuxMode(config PinConfig) uint32 {
|
||||
const forcePath = true // TODO: should be input parameter?
|
||||
switch config.Mode {
|
||||
|
||||
// GPIO
|
||||
case PinInput, PinInputPullUp, PinInputPullDown,
|
||||
PinOutput, PinOutputOpenDrain, PinDisable:
|
||||
mode := uint32(0x5) // GPIO is always alternate function 5
|
||||
if forcePath {
|
||||
mode |= 0x10 // SION bit
|
||||
}
|
||||
return mode
|
||||
|
||||
// ADC
|
||||
case PinInputAnalog:
|
||||
mode := uint32(0x5) // use alternate function 5 (GPIO)
|
||||
if forcePath {
|
||||
mode |= 0x10 // SION bit
|
||||
}
|
||||
return mode
|
||||
|
||||
// UART RX/TX
|
||||
case PinModeUARTRX, PinModeUARTTX:
|
||||
mode := uint32(0x2) // UART is always alternate function 2 on Teensy 4.0
|
||||
// TODO: Teensy 4.1 has a UART (LPUART5) with alternate function 1
|
||||
return mode
|
||||
|
||||
// SPI SDI
|
||||
case PinModeSPISDI:
|
||||
var mode uint32
|
||||
switch p {
|
||||
case PC15: // LPSPI1 SDI on PC15 alternate function 4
|
||||
mode = uint32(0x4)
|
||||
case PA2: // LPSPI3 SDI on PA2 alternate function 7
|
||||
mode = uint32(0x7)
|
||||
case PB1: // LPSPI4 SDI on PB1 alternate function 3
|
||||
mode = uint32(0x3)
|
||||
default:
|
||||
panic("machine: invalid SPI SDI pin")
|
||||
}
|
||||
if forcePath {
|
||||
mode |= 0x10 // SION bit
|
||||
}
|
||||
return mode
|
||||
|
||||
// SPI SDO
|
||||
case PinModeSPISDO:
|
||||
var mode uint32
|
||||
switch p {
|
||||
case PC14: // LPSPI1 SDO on PC14 alternate function 4
|
||||
mode = uint32(0x4)
|
||||
case PA30: // LPSPI3 SDO on PA30 alternate function 2
|
||||
mode = uint32(0x2)
|
||||
case PB2: // LPSPI4 SDO on PB2 alternate function 3
|
||||
mode = uint32(0x3)
|
||||
default:
|
||||
panic("machine: invalid SPI SDO pin")
|
||||
}
|
||||
if forcePath {
|
||||
mode |= 0x10 // SION bit
|
||||
}
|
||||
return mode
|
||||
|
||||
// SPI SCK
|
||||
case PinModeSPICLK:
|
||||
var mode uint32
|
||||
switch p {
|
||||
case PC12: // LPSPI1 SCK on PC12 alternate function 4
|
||||
mode = uint32(0x4)
|
||||
case PA31: // LPSPI3 SCK on PA31 alternate function 2
|
||||
mode = uint32(0x2)
|
||||
case PB3: // LPSPI4 SCK on PB3 alternate function 3
|
||||
mode = uint32(0x3)
|
||||
default:
|
||||
panic("machine: invalid SPI CLK pin")
|
||||
}
|
||||
if forcePath {
|
||||
mode |= 0x10 // SION bit
|
||||
}
|
||||
return mode
|
||||
|
||||
// SPI CS
|
||||
case PinModeSPICS:
|
||||
var mode uint32
|
||||
switch p {
|
||||
case PC13: // LPSPI1 CS on PC13 alternate function 4
|
||||
mode = uint32(0x4)
|
||||
case PA3: // LPSPI3 CS on PA3 alternate function 7
|
||||
mode = uint32(0x7)
|
||||
case PB0: // LPSPI4 CS on PB0 alternate function 3
|
||||
mode = uint32(0x3)
|
||||
default: // use alternate function 5 (GPIO) if non-CS pin selected
|
||||
mode = uint32(0x5)
|
||||
}
|
||||
if forcePath {
|
||||
mode |= 0x10 // SION bit
|
||||
}
|
||||
return mode
|
||||
|
||||
// I2C SDA
|
||||
case PinModeI2CSDA:
|
||||
var mode uint32
|
||||
switch p {
|
||||
case PA13: // LPI2C4 SDA on PA13 alternate function 0
|
||||
mode = uint32(0)
|
||||
case PA17: // LPI2C1 SDA on PA17 alternate function 3
|
||||
mode = uint32(3)
|
||||
case PA22: // LPI2C3 SDA on PA22 alternate function 1
|
||||
mode = uint32(1)
|
||||
default:
|
||||
panic("machine: invalid I2C SDA pin")
|
||||
}
|
||||
if forcePath {
|
||||
mode |= 0x10 // SION bit
|
||||
}
|
||||
return mode
|
||||
|
||||
// I2C SCL
|
||||
case PinModeI2CSCL:
|
||||
var mode uint32
|
||||
switch p {
|
||||
case PA12: // LPI2C4 SCL on PA12 alternate function 0
|
||||
mode = uint32(0)
|
||||
case PA16: // LPI2C1 SCL on PA16 alternate function 3
|
||||
mode = uint32(3)
|
||||
case PA23: // LPI2C3 SCL on PA23 alternate function 1
|
||||
mode = uint32(1)
|
||||
default:
|
||||
panic("machine: invalid I2C SCL pin")
|
||||
}
|
||||
if forcePath {
|
||||
mode |= 0x10 // SION bit
|
||||
}
|
||||
return mode
|
||||
|
||||
default:
|
||||
panic("machine: invalid pin mode")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,325 @@
|
||||
// +build mimxrt1062
|
||||
|
||||
package machine
|
||||
|
||||
import (
|
||||
"device/nxp"
|
||||
"runtime/interrupt"
|
||||
"runtime/volatile"
|
||||
)
|
||||
|
||||
// UART peripheral abstraction layer for the MIMXRT1062
|
||||
|
||||
type UART struct {
|
||||
Bus *nxp.LPUART_Type
|
||||
Buffer *RingBuffer
|
||||
Interrupt interrupt.Interrupt
|
||||
|
||||
// these hold the input selector ("daisy chain") values that select which pins
|
||||
// are connected to the LPUART device, and should be defined where the UART
|
||||
// instance is declared. see the godoc comments on type muxSelect for more
|
||||
// details.
|
||||
muxRX, muxTX muxSelect
|
||||
|
||||
// these are copied from UARTConfig, during (*UART).Configure(UARTConfig), and
|
||||
// should be considered read-only for internal reference (i.e., modifying them
|
||||
// will have no desirable effect).
|
||||
rx, tx Pin
|
||||
baud uint32
|
||||
|
||||
// auxiliary state data used internally
|
||||
configured bool
|
||||
msbFirst bool
|
||||
transmitting volatile.Register32
|
||||
txBuffer *RingBuffer
|
||||
}
|
||||
|
||||
func (uart *UART) isTransmitting() bool { return uart.transmitting.Get() != 0 }
|
||||
func (uart *UART) startTransmitting() { uart.transmitting.Set(1) }
|
||||
func (uart *UART) stopTransmitting() { uart.transmitting.Set(0) }
|
||||
func (uart *UART) resetTransmitting() {
|
||||
uart.stopTransmitting()
|
||||
uart.Bus.GLOBAL.SetBits(nxp.LPUART_GLOBAL_RST)
|
||||
uart.Bus.GLOBAL.ClearBits(nxp.LPUART_GLOBAL_RST)
|
||||
}
|
||||
|
||||
// Configure initializes a UART with the given UARTConfig and other default
|
||||
// settings.
|
||||
func (uart *UART) Configure(config UARTConfig) {
|
||||
|
||||
const defaultUartFreq = 115200
|
||||
|
||||
// use default baud rate if not specified
|
||||
if config.BaudRate == 0 {
|
||||
config.BaudRate = defaultUartFreq
|
||||
}
|
||||
uart.baud = config.BaudRate
|
||||
|
||||
// use default UART pins if not specified
|
||||
if config.RX == 0 && config.TX == 0 {
|
||||
config.RX = UART_RX_PIN
|
||||
config.TX = UART_TX_PIN
|
||||
}
|
||||
uart.rx = config.RX
|
||||
uart.tx = config.TX
|
||||
|
||||
// configure the mux and pad control registers
|
||||
uart.rx.Configure(PinConfig{Mode: PinModeUARTRX})
|
||||
uart.tx.Configure(PinConfig{Mode: PinModeUARTTX})
|
||||
|
||||
// configure the mux input selector
|
||||
uart.muxRX.connect()
|
||||
uart.muxTX.connect()
|
||||
|
||||
// reset all internal logic and registers
|
||||
uart.resetTransmitting()
|
||||
|
||||
// determine the baud rate and over-sample divisors
|
||||
sbr, osr := uart.getBaudRateDivisor(uart.baud)
|
||||
|
||||
// for now we assume some configuration. in particular:
|
||||
// Data bits -> 8-bit
|
||||
// Parity bit -> None (parity bit generation disabled)
|
||||
// Stop bits -> 1 stop bit
|
||||
// MSB first -> false
|
||||
// RX idle type -> idle count starts after start bit
|
||||
// RX idle config -> 1 idle character
|
||||
// RX RTS enabled -> false
|
||||
// TX CTS enabled -> false
|
||||
|
||||
// set the baud rate, over-sample configuration, stop bits
|
||||
baudBits := (((osr - 1) << nxp.LPUART_BAUD_OSR_Pos) & nxp.LPUART_BAUD_OSR_Msk) |
|
||||
((sbr << nxp.LPUART_BAUD_SBR_Pos) & nxp.LPUART_BAUD_SBR_Msk) |
|
||||
((nxp.LPUART_BAUD_SBNS_SBNS_0 << nxp.LPUART_BAUD_SBNS_Pos) & nxp.LPUART_BAUD_SBNS_Msk)
|
||||
if osr <= 8 {
|
||||
// if OSR less than or equal to 8, we must enable sampling on both edges
|
||||
baudBits |= nxp.LPUART_BAUD_BOTHEDGE
|
||||
}
|
||||
uart.Bus.BAUD.Set(baudBits)
|
||||
|
||||
uart.Bus.PINCFG.Set(0) // disable triggers
|
||||
|
||||
// use 8 data bits, disable parity, use 1 idle char, and idle count starts
|
||||
// after start bit
|
||||
ctrlBits := uint32(((nxp.LPUART_CTRL_M_M_0 << nxp.LPUART_CTRL_M_Pos) & nxp.LPUART_CTRL_M_Msk) |
|
||||
((nxp.LPUART_CTRL_PE_PE_0 << nxp.LPUART_CTRL_PE_Pos) & nxp.LPUART_CTRL_PE_Msk) |
|
||||
((nxp.LPUART_CTRL_ILT_ILT_0 << nxp.LPUART_CTRL_ILT_Pos) & nxp.LPUART_CTRL_ILT_Msk) |
|
||||
((nxp.LPUART_CTRL_IDLECFG_IDLECFG_0 << nxp.LPUART_CTRL_IDLECFG_Pos) & nxp.LPUART_CTRL_IDLECFG_Msk))
|
||||
uart.Bus.CTRL.Set(ctrlBits)
|
||||
|
||||
rxSize, txSize := uart.getFIFOSize()
|
||||
|
||||
rxWater := rxSize >> 1
|
||||
if rxWater > uint32(nxp.LPUART_FIFO_RXFIFOSIZE_Msk>>nxp.LPUART_FIFO_RXFIFOSIZE_Pos) {
|
||||
rxWater = uint32(nxp.LPUART_FIFO_RXFIFOSIZE_Msk >> nxp.LPUART_FIFO_RXFIFOSIZE_Pos)
|
||||
}
|
||||
|
||||
txWater := txSize >> 1
|
||||
if txWater > uint32(nxp.LPUART_FIFO_TXFIFOSIZE_Msk>>nxp.LPUART_FIFO_TXFIFOSIZE_Pos) {
|
||||
txWater = uint32(nxp.LPUART_FIFO_TXFIFOSIZE_Msk >> nxp.LPUART_FIFO_TXFIFOSIZE_Pos)
|
||||
}
|
||||
|
||||
uart.Bus.WATER.Set(
|
||||
((rxWater << nxp.LPUART_WATER_RXWATER_Pos) & nxp.LPUART_WATER_RXWATER_Msk) |
|
||||
((txWater << nxp.LPUART_WATER_TXWATER_Pos) & nxp.LPUART_WATER_TXWATER_Msk))
|
||||
|
||||
// enable TX/RX FIFOs
|
||||
uart.Bus.FIFO.SetBits(nxp.LPUART_FIFO_RXFE | nxp.LPUART_FIFO_TXFE)
|
||||
|
||||
// flush TX/RX FIFOs
|
||||
uart.Bus.FIFO.SetBits(nxp.LPUART_FIFO_RXFLUSH | nxp.LPUART_FIFO_TXFLUSH)
|
||||
|
||||
uart.Bus.MODIR.SetBits( // set the CTS configuration/TX CTS source
|
||||
((nxp.LPUART_MODIR_TXCTSC_TXCTSC_0 << nxp.LPUART_MODIR_TXCTSC_Pos) & nxp.LPUART_MODIR_TXCTSC_Msk) |
|
||||
((nxp.LPUART_MODIR_TXCTSSRC_TXCTSSRC_0 << nxp.LPUART_MODIR_TXCTSSRC_Pos) & nxp.LPUART_MODIR_TXCTSSRC_Msk))
|
||||
|
||||
// clear all status flags
|
||||
stat := uint32(nxp.LPUART_STAT_RXEDGIF_Msk | nxp.LPUART_STAT_IDLE_Msk | nxp.LPUART_STAT_OR_Msk |
|
||||
nxp.LPUART_STAT_NF_Msk | nxp.LPUART_STAT_FE_Msk | nxp.LPUART_STAT_PF_Msk |
|
||||
nxp.LPUART_STAT_LBKDIF_Msk | nxp.LPUART_STAT_MA1F_Msk | nxp.LPUART_STAT_MA2F_Msk)
|
||||
|
||||
// set data bits order
|
||||
if uart.msbFirst {
|
||||
stat |= nxp.LPUART_STAT_MSBF
|
||||
} else {
|
||||
stat &^= nxp.LPUART_STAT_MSBF
|
||||
}
|
||||
|
||||
uart.Bus.STAT.SetBits(stat)
|
||||
|
||||
// enable RX/TX functions
|
||||
uart.Bus.CTRL.SetBits(nxp.LPUART_CTRL_TE | nxp.LPUART_CTRL_RE)
|
||||
|
||||
// enable RX IRQ
|
||||
uart.Interrupt.SetPriority(0xc0)
|
||||
uart.Interrupt.Enable()
|
||||
|
||||
uart.configured = true
|
||||
}
|
||||
|
||||
// Disable disables the UART interface.
|
||||
//
|
||||
// If any buffered data has not yet been transmitted, Disable waits until
|
||||
// transmission completes before disabling the interface. The receiver UART's
|
||||
// interrupt is also disabled, and the RX/TX pins are reconfigured for GPIO
|
||||
// input (pull-up).
|
||||
func (uart *UART) Disable() {
|
||||
|
||||
// first ensure the device is enabled
|
||||
if uart.configured {
|
||||
|
||||
// wait for any buffered data to send
|
||||
uart.Sync()
|
||||
|
||||
// stop trapping RX interrupts
|
||||
uart.Interrupt.Disable()
|
||||
|
||||
// reset all internal registers
|
||||
uart.resetTransmitting()
|
||||
|
||||
// disable RX/TX functions
|
||||
uart.Bus.CTRL.ClearBits(nxp.LPUART_CTRL_TE | nxp.LPUART_CTRL_RE)
|
||||
|
||||
// put pins back into GPIO mode
|
||||
uart.rx.Configure(PinConfig{Mode: PinInputPullUp})
|
||||
uart.tx.Configure(PinConfig{Mode: PinInputPullUp})
|
||||
}
|
||||
uart.configured = false
|
||||
}
|
||||
|
||||
// Sync blocks the calling goroutine until all data in the output buffer has
|
||||
// been transmitted.
|
||||
func (uart *UART) Sync() error {
|
||||
for uart.isTransmitting() {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteByte writes a single byte of data to the UART interface.
|
||||
func (uart *UART) WriteByte(c byte) error {
|
||||
if nil == uart.txBuffer {
|
||||
uart.txBuffer = NewRingBuffer()
|
||||
}
|
||||
uart.startTransmitting()
|
||||
for !uart.txBuffer.Put(c) {
|
||||
}
|
||||
uart.Bus.CTRL.SetBits(nxp.LPUART_CTRL_TIE)
|
||||
return nil
|
||||
}
|
||||
|
||||
// getBaudRateDivisor finds the greatest over-sampling factor (4..32) and
|
||||
// corresponding baud rate divisor (1..8191) that best partition a given baud
|
||||
// rate into equal intervals.
|
||||
//
|
||||
// This is an integral (i.e. non-floating point) port of the logic at the
|
||||
// beginning of:
|
||||
// void HardwareSerial::begin(uint32_t baud, uint16_t format)
|
||||
// (from Teensyduino: `cores/teensy4/HardwareSerial.cpp`)
|
||||
//
|
||||
// We don't want to risk using floating point here in the machine package in
|
||||
// case it gets called before the FPU or interrupts are ready (e.g., init()).
|
||||
func (uart *UART) getBaudRateDivisor(baudRate uint32) (sbr uint32, osr uint32) {
|
||||
const clock = 24000000 // UART is muxed to 24 MHz OSC
|
||||
err := uint32(0xFFFFFFFF)
|
||||
sbr, osr = 0, 0
|
||||
for o := uint32(4); o <= 32; o++ {
|
||||
s := ((clock*10)/(baudRate*o) + 5) / 10
|
||||
if s == 0 {
|
||||
s = 1
|
||||
}
|
||||
b := clock / (s * o)
|
||||
var e uint32
|
||||
if b > baudRate {
|
||||
e = b - baudRate
|
||||
} else {
|
||||
e = baudRate - b
|
||||
}
|
||||
if e <= err {
|
||||
err = e
|
||||
osr = o
|
||||
sbr = s
|
||||
}
|
||||
}
|
||||
return sbr, osr
|
||||
}
|
||||
|
||||
func (uart *UART) getFIFOSize() (rx, tx uint32) {
|
||||
fifo := uart.Bus.FIFO.Get()
|
||||
rx = uint32(1) << ((fifo & nxp.LPUART_FIFO_RXFIFOSIZE_Msk) >> nxp.LPUART_FIFO_RXFIFOSIZE_Pos)
|
||||
if rx > 1 {
|
||||
rx <<= 1
|
||||
}
|
||||
tx = uint32(1) << ((fifo & nxp.LPUART_FIFO_TXFIFOSIZE_Msk) >> nxp.LPUART_FIFO_TXFIFOSIZE_Pos)
|
||||
if tx > 1 {
|
||||
tx <<= 1
|
||||
}
|
||||
return rx, tx
|
||||
}
|
||||
|
||||
func (uart *UART) getStatus() uint32 {
|
||||
return uart.Bus.STAT.Get() |
|
||||
((uart.Bus.FIFO.Get() & uint32(nxp.LPUART_FIFO_TXEMPT_Msk|nxp.LPUART_FIFO_RXEMPT_Msk|
|
||||
nxp.LPUART_FIFO_TXOF_Msk|nxp.LPUART_FIFO_RXUF_Msk)) >> 16)
|
||||
}
|
||||
|
||||
func (uart *UART) getEnabledInterrupts() uint32 {
|
||||
return ((uart.Bus.BAUD.Get() & uint32(nxp.LPUART_BAUD_LBKDIE_Msk|nxp.LPUART_BAUD_RXEDGIE_Msk)) >> 8) |
|
||||
((uart.Bus.FIFO.Get() & uint32(nxp.LPUART_FIFO_TXOFE_Msk|nxp.LPUART_FIFO_RXUFE_Msk)) >> 8) |
|
||||
(uart.Bus.CTRL.Get() & uint32(0xFF0C000))
|
||||
}
|
||||
|
||||
func (uart *UART) disableInterrupts(mask uint32) {
|
||||
uart.Bus.BAUD.ClearBits((mask << 8) & uint32(nxp.LPUART_BAUD_LBKDIE_Msk|nxp.LPUART_BAUD_RXEDGIE_Msk))
|
||||
uart.Bus.FIFO.Set((uart.Bus.FIFO.Get() & ^uint32(nxp.LPUART_FIFO_TXOF_Msk|nxp.LPUART_FIFO_RXUF_Msk)) &
|
||||
^uint32((mask<<8)&(nxp.LPUART_FIFO_TXOFE_Msk|nxp.LPUART_FIFO_RXUFE_Msk)))
|
||||
mask &= uint32(0xFFFFFF00)
|
||||
uart.Bus.CTRL.ClearBits(mask)
|
||||
}
|
||||
|
||||
func (uart *UART) handleInterrupt(interrupt.Interrupt) {
|
||||
|
||||
stat := uart.getStatus()
|
||||
inte := uart.getEnabledInterrupts()
|
||||
|
||||
_, txSize := uart.getFIFOSize()
|
||||
|
||||
// check for and clear overrun, otherwise RX will not work
|
||||
if (stat & uint32(nxp.LPUART_STAT_OR)) != 0 {
|
||||
uart.Bus.STAT.Set((uart.Bus.STAT.Get() & uint32(0x3FE00000)) | nxp.LPUART_STAT_OR)
|
||||
}
|
||||
|
||||
// idle or receive data register is full
|
||||
if (stat & uint32(nxp.LPUART_STAT_RDRF|nxp.LPUART_STAT_IDLE)) != 0 {
|
||||
count := (uart.Bus.WATER.Get() & uint32(nxp.LPUART_WATER_RXCOUNT_Msk)) >> nxp.LPUART_WATER_RXCOUNT_Pos
|
||||
for ; count > 0; count-- {
|
||||
// read up to 8 bits of data at a time
|
||||
// TODO: 7, 9, and 10-bit support?
|
||||
uart.Buffer.Put(uint8(uart.Bus.DATA.Get() & uint32(0xFF)))
|
||||
}
|
||||
// if it was an IDLE status, clear the flag
|
||||
if (stat & uint32(nxp.LPUART_STAT_IDLE)) != 0 {
|
||||
uart.Bus.STAT.SetBits(nxp.LPUART_STAT_IDLE)
|
||||
}
|
||||
// disable idle line interrupts
|
||||
uart.disableInterrupts(nxp.LPUART_CTRL_RIE | nxp.LPUART_CTRL_ORIE)
|
||||
}
|
||||
|
||||
// check if we have data to write
|
||||
if ((inte & nxp.LPUART_CTRL_TIE) != 0) && ((stat & nxp.LPUART_STAT_TDRE) != 0) {
|
||||
for ((uart.Bus.WATER.Get() & uint32(nxp.LPUART_WATER_TXCOUNT_Msk)) >> nxp.LPUART_WATER_TXCOUNT_Pos) < txSize {
|
||||
if b, ok := uart.txBuffer.Get(); ok {
|
||||
uart.Bus.DATA.Set(uint32(b))
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
if uart.Bus.STAT.HasBits(nxp.LPUART_STAT_TDRE) {
|
||||
uart.Bus.CTRL.Set((uart.Bus.CTRL.Get() & ^uint32(nxp.LPUART_CTRL_TIE)) | nxp.LPUART_CTRL_TCIE)
|
||||
}
|
||||
}
|
||||
|
||||
if ((inte & nxp.LPUART_CTRL_TCIE) != 0) && ((stat & nxp.LPUART_STAT_TC) != 0) {
|
||||
uart.stopTransmitting()
|
||||
uart.Bus.CTRL.ClearBits(nxp.LPUART_CTRL_TCIE)
|
||||
}
|
||||
}
|
||||
+44
-23
@@ -72,7 +72,8 @@ func (p Pin) Get() bool {
|
||||
}
|
||||
|
||||
// SetInterrupt sets an interrupt to be executed when a particular pin changes
|
||||
// state.
|
||||
// state. The pin should already be configured as an input, including a pull up
|
||||
// or down if no external pull is provided.
|
||||
//
|
||||
// This call will replace a previously set callback on this pin. You can pass a
|
||||
// nil func to unset the pin change interrupt. If you do so, the change
|
||||
@@ -258,12 +259,15 @@ func (i2c I2C) Configure(config I2CConfig) {
|
||||
// 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 {
|
||||
func (i2c I2C) Tx(addr uint16, w, r []byte) (err error) {
|
||||
i2c.Bus.ADDRESS.Set(uint32(addr))
|
||||
|
||||
if len(w) != 0 {
|
||||
i2c.Bus.TASKS_STARTTX.Set(1) // start transmission for writing
|
||||
for _, b := range w {
|
||||
i2c.writeByte(b)
|
||||
if err = i2c.writeByte(b); err != nil {
|
||||
goto cleanUp
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(r) != 0 {
|
||||
@@ -276,12 +280,18 @@ func (i2c I2C) Tx(addr uint16, w, r []byte) error {
|
||||
i2c.Bus.SHORTS.Set(nrf.TWI_SHORTS_BB_STOP)
|
||||
}
|
||||
i2c.Bus.TASKS_RESUME.Set(1) // re-start transmission for reading
|
||||
r[i] = i2c.readByte()
|
||||
if r[i], err = i2c.readByte(); err != nil {
|
||||
// goto/break are practically equivalent here,
|
||||
// but goto makes this more easily understandable for maintenance.
|
||||
goto cleanUp
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cleanUp:
|
||||
i2c.signalStop()
|
||||
i2c.Bus.SHORTS.Set(nrf.TWI_SHORTS_BB_SUSPEND_Disabled)
|
||||
return nil
|
||||
return
|
||||
}
|
||||
|
||||
// signalStop sends a stop signal when writing or tells the I2C peripheral that
|
||||
@@ -295,19 +305,28 @@ func (i2c I2C) signalStop() {
|
||||
}
|
||||
|
||||
// writeByte writes a single byte to the I2C bus.
|
||||
func (i2c I2C) writeByte(data byte) {
|
||||
func (i2c I2C) writeByte(data byte) error {
|
||||
i2c.Bus.TXD.Set(uint32(data))
|
||||
for i2c.Bus.EVENTS_TXDSENT.Get() == 0 {
|
||||
if e := i2c.Bus.EVENTS_ERROR.Get(); e != 0 {
|
||||
i2c.Bus.EVENTS_ERROR.Set(0)
|
||||
return errI2CBusError
|
||||
}
|
||||
}
|
||||
i2c.Bus.EVENTS_TXDSENT.Set(0)
|
||||
return nil
|
||||
}
|
||||
|
||||
// readByte reads a single byte from the I2C bus.
|
||||
func (i2c I2C) readByte() byte {
|
||||
func (i2c I2C) readByte() (byte, error) {
|
||||
for i2c.Bus.EVENTS_RXDREADY.Get() == 0 {
|
||||
if e := i2c.Bus.EVENTS_ERROR.Get(); e != 0 {
|
||||
i2c.Bus.EVENTS_ERROR.Set(0)
|
||||
return 0, errI2CBusError
|
||||
}
|
||||
}
|
||||
i2c.Bus.EVENTS_RXDREADY.Set(0)
|
||||
return byte(i2c.Bus.RXD.Get())
|
||||
return byte(i2c.Bus.RXD.Get()), nil
|
||||
}
|
||||
|
||||
// SPI on the NRF.
|
||||
@@ -339,23 +358,25 @@ func (spi SPI) Configure(config SPIConfig) {
|
||||
// set frequency
|
||||
var freq uint32
|
||||
|
||||
switch config.Frequency {
|
||||
case 125000:
|
||||
freq = nrf.SPI_FREQUENCY_FREQUENCY_K125
|
||||
case 250000:
|
||||
freq = nrf.SPI_FREQUENCY_FREQUENCY_K250
|
||||
case 500000:
|
||||
freq = nrf.SPI_FREQUENCY_FREQUENCY_K500
|
||||
case 1000000:
|
||||
freq = nrf.SPI_FREQUENCY_FREQUENCY_M1
|
||||
case 2000000:
|
||||
freq = nrf.SPI_FREQUENCY_FREQUENCY_M2
|
||||
case 4000000:
|
||||
freq = nrf.SPI_FREQUENCY_FREQUENCY_M4
|
||||
case 8000000:
|
||||
if config.Frequency == 0 {
|
||||
config.Frequency = 4000000 // 4MHz
|
||||
}
|
||||
|
||||
switch {
|
||||
case config.Frequency >= 8000000:
|
||||
freq = nrf.SPI_FREQUENCY_FREQUENCY_M8
|
||||
default:
|
||||
case config.Frequency >= 4000000:
|
||||
freq = nrf.SPI_FREQUENCY_FREQUENCY_M4
|
||||
case config.Frequency >= 2000000:
|
||||
freq = nrf.SPI_FREQUENCY_FREQUENCY_M2
|
||||
case config.Frequency >= 1000000:
|
||||
freq = nrf.SPI_FREQUENCY_FREQUENCY_M1
|
||||
case config.Frequency >= 500000:
|
||||
freq = nrf.SPI_FREQUENCY_FREQUENCY_K500
|
||||
case config.Frequency >= 250000:
|
||||
freq = nrf.SPI_FREQUENCY_FREQUENCY_K250
|
||||
default: // below 250kHz, default to the lowest speed available
|
||||
freq = nrf.SPI_FREQUENCY_FREQUENCY_K125
|
||||
}
|
||||
spi.Bus.FREQUENCY.Set(freq)
|
||||
|
||||
|
||||
@@ -0,0 +1,481 @@
|
||||
// +build stm32,!stm32f103xx,!stm32f407
|
||||
|
||||
package machine
|
||||
|
||||
// Peripheral abstraction layer for I2C on the stm32 family
|
||||
|
||||
import (
|
||||
"device/stm32"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
flagOVR = 0x00010800
|
||||
flagAF = 0x00010400
|
||||
flagARLO = 0x00010200
|
||||
flagBERR = 0x00010100
|
||||
flagTXE = 0x00010080
|
||||
flagRXNE = 0x00010040
|
||||
flagSTOPF = 0x00010010
|
||||
flagADD10 = 0x00010008
|
||||
flagBTF = 0x00010004
|
||||
flagADDR = 0x00010002
|
||||
flagSB = 0x00010001
|
||||
flagDUALF = 0x00100080
|
||||
flagGENCALL = 0x00100010
|
||||
flagTRA = 0x00100004
|
||||
flagBUSY = 0x00100002
|
||||
flagMSL = 0x00100001
|
||||
)
|
||||
|
||||
func (i2c I2C) hasFlag(flag uint32) bool {
|
||||
const mask = 0x0000FFFF
|
||||
if uint8(flag>>16) == 1 {
|
||||
return i2c.Bus.SR1.HasBits(flag & mask)
|
||||
} else {
|
||||
return i2c.Bus.SR2.HasBits(flag & mask)
|
||||
}
|
||||
}
|
||||
|
||||
func (i2c I2C) clearFlag(flag uint32) {
|
||||
const mask = 0x0000FFFF
|
||||
i2c.Bus.SR1.Set(^(flag & mask))
|
||||
}
|
||||
|
||||
// clearFlagADDR reads both status registers to clear any pending ADDR flags.
|
||||
func (i2c I2C) clearFlagADDR() {
|
||||
i2c.Bus.SR1.Get()
|
||||
i2c.Bus.SR2.Get()
|
||||
}
|
||||
|
||||
func (i2c I2C) waitForFlag(flag uint32, set bool) bool {
|
||||
const tryMax = 10000
|
||||
hasFlag := false
|
||||
for i := 0; !hasFlag && i < tryMax; i++ {
|
||||
hasFlag = i2c.hasFlag(flag) == set
|
||||
}
|
||||
return hasFlag
|
||||
}
|
||||
|
||||
func (i2c I2C) waitForFlagOrError(flag uint32, set bool) bool {
|
||||
const tryMax = 10000
|
||||
hasFlag := false
|
||||
for i := 0; !hasFlag && i < tryMax; i++ {
|
||||
if hasFlag = i2c.hasFlag(flag) == set; !hasFlag {
|
||||
// check for ACK failure
|
||||
if i2c.hasFlag(flagAF) {
|
||||
// generate stop condition
|
||||
i2c.Bus.CR1.SetBits(stm32.I2C_CR1_STOP)
|
||||
// clear pending flags
|
||||
i2c.clearFlag(flagAF)
|
||||
return false
|
||||
} else if i2c.hasFlag(flagSTOPF) {
|
||||
// clear stop flag
|
||||
i2c.clearFlag(flagSTOPF)
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return hasFlag
|
||||
}
|
||||
|
||||
type transferOption uint32
|
||||
|
||||
const (
|
||||
frameFirst = 0x00000001
|
||||
frameFirstAndNext = 0x00000002
|
||||
frameNext = 0x00000004
|
||||
frameFirstAndLast = 0x00000008
|
||||
frameLastNoStop = 0x00000010
|
||||
frameLast = 0x00000020
|
||||
frameNoOption = 0xFFFF0000
|
||||
)
|
||||
|
||||
// addressable represents a type that can provide fully-formatted I2C peripheral
|
||||
// addresses for both read operations and write operations.
|
||||
type addressable interface {
|
||||
toRead() uint32
|
||||
toWrite() uint32
|
||||
bitSize() uint8
|
||||
}
|
||||
|
||||
// address7Bit and address10Bit stores the unshifted original I2C peripheral address
|
||||
// in an unsigned integral data type and implements the addressable interface
|
||||
// to reformat addresses as required for read/write operations.
|
||||
// TODO:
|
||||
// add 10-bit address support
|
||||
type (
|
||||
address7Bit uint8
|
||||
//address10Bit uint16
|
||||
)
|
||||
|
||||
func (sa address7Bit) toRead() uint32 {
|
||||
return uint32(((uint8(sa) << 1) | uint8(stm32.I2C_OAR1_ADD0)) & 0xFF)
|
||||
}
|
||||
func (sa address7Bit) toWrite() uint32 {
|
||||
return uint32(((uint8(sa) << 1) & ^(uint8(stm32.I2C_OAR1_ADD0))) & 0xFF)
|
||||
}
|
||||
func (sa address7Bit) bitSize() uint8 { return 7 } // 7-bit addresses
|
||||
|
||||
//func (sa address10Bit) toRead() uint32 {}
|
||||
//func (sa address10Bit) toWrite() uint32 {}
|
||||
//func (sa address10Bit) bitSize() uint8 { return 10 } // 10-bit addresses
|
||||
|
||||
func readAddress7Bit(addr uint8) uint32 { return address7Bit(addr).toRead() }
|
||||
func writeAddress7Bit(addr uint8) uint32 { return address7Bit(addr).toWrite() }
|
||||
|
||||
//func readAddress10Bit(addr uint16) uint32 { return address10Bit(addr).toRead() }
|
||||
//func writeAddress10Bit(addr uint16) uint32 { return address10Bit(addr).toWrite() }
|
||||
|
||||
// I2C fast mode (Fm) duty cycle
|
||||
const (
|
||||
DutyCycle2 = 0
|
||||
DutyCycle16x9 = 1
|
||||
)
|
||||
|
||||
// I2CConfig is used to store config info for I2C.
|
||||
type I2CConfig struct {
|
||||
Frequency uint32
|
||||
SCL Pin
|
||||
SDA Pin
|
||||
DutyCycle uint8
|
||||
}
|
||||
|
||||
// Configure is intended to setup the STM32 I2C interface.
|
||||
func (i2c I2C) Configure(config I2CConfig) {
|
||||
|
||||
// The following is the required sequence in controller mode.
|
||||
// 1. Program the peripheral input clock in I2C_CR2 Register in order to
|
||||
// generate correct timings
|
||||
// 2. Configure the clock control registers
|
||||
// 3. Configure the rise time register
|
||||
// 4. Program the I2C_CR1 register to enable the peripheral
|
||||
// 5. Set the START bit in the I2C_CR1 register to generate a Start condition
|
||||
|
||||
// disable I2C interface before any configuration changes
|
||||
i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_PE)
|
||||
|
||||
// reset I2C bus
|
||||
i2c.Bus.CR1.SetBits(stm32.I2C_CR1_SWRST)
|
||||
i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_SWRST)
|
||||
|
||||
// enable clock for I2C
|
||||
enableAltFuncClock(unsafe.Pointer(i2c.Bus))
|
||||
|
||||
// init pins
|
||||
if config.SCL == 0 && config.SDA == 0 {
|
||||
config.SCL = I2C0_SCL_PIN
|
||||
config.SDA = I2C0_SDA_PIN
|
||||
}
|
||||
i2c.configurePins(config)
|
||||
|
||||
// default to 100 kHz (Sm, standard mode) if no frequency is set
|
||||
if config.Frequency == 0 {
|
||||
config.Frequency = TWI_FREQ_100KHZ
|
||||
}
|
||||
|
||||
// configure I2C input clock
|
||||
i2c.Bus.CR2.SetBits(i2c.getFreqRange(config))
|
||||
|
||||
// configure rise time
|
||||
i2c.Bus.TRISE.Set(i2c.getRiseTime(config))
|
||||
|
||||
// configure clock control
|
||||
i2c.Bus.CCR.Set(i2c.getSpeed(config))
|
||||
|
||||
// disable GeneralCall and NoStretch modes
|
||||
i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_ENGC | stm32.I2C_CR1_NOSTRETCH)
|
||||
|
||||
// enable I2C interface
|
||||
i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_PE)
|
||||
}
|
||||
|
||||
func (i2c I2C) Tx(addr uint16, w, r []byte) error {
|
||||
a := address7Bit(addr)
|
||||
if err := i2c.controllerTransmit(a, w); nil != err {
|
||||
return err
|
||||
}
|
||||
if err := i2c.controllerReceive(a, r); nil != err {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i2c I2C) controllerTransmit(addr addressable, w []byte) error {
|
||||
|
||||
if !i2c.waitForFlag(flagBUSY, false) {
|
||||
return errI2CBusReadyTimeout
|
||||
}
|
||||
|
||||
// ensure peripheral is enabled
|
||||
if !i2c.Bus.CR1.HasBits(stm32.I2C_CR1_PE) {
|
||||
i2c.Bus.CR1.SetBits(stm32.I2C_CR1_PE)
|
||||
}
|
||||
|
||||
// disable POS
|
||||
i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_POS)
|
||||
|
||||
pos := 0
|
||||
rem := len(w)
|
||||
|
||||
// send peripheral address
|
||||
if err := i2c.controllerRequestWrite(addr, frameNoOption); nil != err {
|
||||
return err
|
||||
}
|
||||
|
||||
// clear ADDR flag
|
||||
i2c.clearFlagADDR()
|
||||
|
||||
for rem > 0 {
|
||||
// wait for TXE flag set
|
||||
if !i2c.waitForFlagOrError(flagTXE, true) {
|
||||
return errI2CAckExpected
|
||||
}
|
||||
|
||||
// write data to DR
|
||||
i2c.Bus.DR.Set(uint32(w[pos]))
|
||||
// update counters
|
||||
pos++
|
||||
rem--
|
||||
|
||||
if i2c.hasFlag(flagBTF) && rem != 0 {
|
||||
// write data to DR
|
||||
i2c.Bus.DR.Set(uint32(w[pos]))
|
||||
// update counters
|
||||
pos++
|
||||
rem--
|
||||
}
|
||||
|
||||
// wait for transfer finished flag BTF set
|
||||
if !i2c.waitForFlagOrError(flagBTF, true) {
|
||||
return errI2CWriteTimeout
|
||||
}
|
||||
}
|
||||
|
||||
// generate stop condition
|
||||
i2c.Bus.CR1.SetBits(stm32.I2C_CR1_STOP)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i2c I2C) controllerRequestWrite(addr addressable, option transferOption) error {
|
||||
|
||||
if frameFirstAndLast == option || frameFirst == option || frameNoOption == option {
|
||||
// generate start condition
|
||||
i2c.Bus.CR1.SetBits(stm32.I2C_CR1_START)
|
||||
} else if false /* (hi2c->PreviousState == I2C_STATE_MASTER_BUSY_RX) */ {
|
||||
// generate restart condition
|
||||
i2c.Bus.CR1.SetBits(stm32.I2C_CR1_START)
|
||||
}
|
||||
|
||||
// ensure start bit is set
|
||||
if !i2c.waitForFlag(flagSB, true) {
|
||||
return errI2CSignalStartTimeout
|
||||
}
|
||||
|
||||
// send peripheral address
|
||||
switch addr.bitSize() {
|
||||
case 7: // 7-bit peripheral address
|
||||
i2c.Bus.DR.Set(addr.toWrite())
|
||||
|
||||
case 10: // 10-bit peripheral address
|
||||
// TODO
|
||||
}
|
||||
|
||||
// wait for address ACK from peripheral
|
||||
if !i2c.waitForFlagOrError(flagADDR, true) {
|
||||
return errI2CSignalStartTimeout
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i2c I2C) controllerReceive(addr addressable, r []byte) error {
|
||||
|
||||
if !i2c.waitForFlag(flagBUSY, false) {
|
||||
return errI2CBusReadyTimeout
|
||||
}
|
||||
|
||||
// ensure peripheral is enabled
|
||||
if !i2c.Bus.CR1.HasBits(stm32.I2C_CR1_PE) {
|
||||
i2c.Bus.CR1.SetBits(stm32.I2C_CR1_PE)
|
||||
}
|
||||
|
||||
// disable POS
|
||||
i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_POS)
|
||||
|
||||
pos := 0
|
||||
rem := len(r)
|
||||
|
||||
// send peripheral address
|
||||
if err := i2c.controllerRequestRead(addr, frameNoOption); nil != err {
|
||||
return err
|
||||
}
|
||||
|
||||
switch rem {
|
||||
case 0:
|
||||
// clear ADDR flag
|
||||
i2c.clearFlagADDR()
|
||||
// generate stop condition
|
||||
i2c.Bus.CR1.SetBits(stm32.I2C_CR1_STOP)
|
||||
|
||||
case 1:
|
||||
// disable ACK
|
||||
i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_ACK)
|
||||
// clear ADDR flag
|
||||
i2c.clearFlagADDR()
|
||||
// generate stop condition
|
||||
i2c.Bus.CR1.SetBits(stm32.I2C_CR1_STOP)
|
||||
|
||||
case 2:
|
||||
// disable ACK
|
||||
i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_ACK)
|
||||
// enable POS
|
||||
i2c.Bus.CR1.SetBits(stm32.I2C_CR1_POS)
|
||||
// clear ADDR flag
|
||||
i2c.clearFlagADDR()
|
||||
|
||||
default:
|
||||
// enable ACK
|
||||
i2c.Bus.CR1.SetBits(stm32.I2C_CR1_ACK)
|
||||
// clear ADDR flag
|
||||
i2c.clearFlagADDR()
|
||||
}
|
||||
|
||||
for rem > 0 {
|
||||
switch rem {
|
||||
case 1:
|
||||
// wait until RXNE flag is set
|
||||
if !i2c.waitForFlagOrError(flagRXNE, true) {
|
||||
return errI2CReadTimeout
|
||||
}
|
||||
|
||||
// read data from DR
|
||||
r[pos] = byte(i2c.Bus.DR.Get())
|
||||
|
||||
// update counters
|
||||
pos++
|
||||
rem--
|
||||
|
||||
case 2:
|
||||
// wait until transfer finished flag BTF is set
|
||||
if !i2c.waitForFlag(flagBTF, true) {
|
||||
return errI2CReadTimeout
|
||||
}
|
||||
|
||||
// generate stop condition
|
||||
i2c.Bus.CR1.SetBits(stm32.I2C_CR1_STOP)
|
||||
|
||||
// read data from DR
|
||||
r[pos] = byte(i2c.Bus.DR.Get())
|
||||
|
||||
// update counters
|
||||
pos++
|
||||
rem--
|
||||
|
||||
// read data from DR
|
||||
r[pos] = byte(i2c.Bus.DR.Get())
|
||||
|
||||
// update counters
|
||||
pos++
|
||||
rem--
|
||||
|
||||
case 3:
|
||||
// wait until transfer finished flag BTF is set
|
||||
if !i2c.waitForFlag(flagBTF, true) {
|
||||
return errI2CReadTimeout
|
||||
}
|
||||
|
||||
// disable ACK
|
||||
i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_ACK)
|
||||
|
||||
// read data from DR
|
||||
r[pos] = byte(i2c.Bus.DR.Get())
|
||||
|
||||
// update counters
|
||||
pos++
|
||||
rem--
|
||||
|
||||
// wait until transfer finished flag BTF is set
|
||||
if !i2c.waitForFlag(flagBTF, true) {
|
||||
return errI2CReadTimeout
|
||||
}
|
||||
|
||||
// generate stop condition
|
||||
i2c.Bus.CR1.SetBits(stm32.I2C_CR1_STOP)
|
||||
|
||||
// read data from DR
|
||||
r[pos] = byte(i2c.Bus.DR.Get())
|
||||
|
||||
// update counters
|
||||
pos++
|
||||
rem--
|
||||
|
||||
// read data from DR
|
||||
r[pos] = byte(i2c.Bus.DR.Get())
|
||||
|
||||
// update counters
|
||||
pos++
|
||||
rem--
|
||||
|
||||
default:
|
||||
// wait until RXNE flag is set
|
||||
if !i2c.waitForFlagOrError(flagRXNE, true) {
|
||||
return errI2CReadTimeout
|
||||
}
|
||||
|
||||
// read data from DR
|
||||
r[pos] = byte(i2c.Bus.DR.Get())
|
||||
|
||||
// update counters
|
||||
pos++
|
||||
rem--
|
||||
|
||||
if i2c.hasFlag(flagBTF) {
|
||||
// read data from DR
|
||||
r[pos] = byte(i2c.Bus.DR.Get())
|
||||
|
||||
// update counters
|
||||
pos++
|
||||
rem--
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i2c I2C) controllerRequestRead(addr addressable, option transferOption) error {
|
||||
|
||||
// enable ACK
|
||||
i2c.Bus.CR1.SetBits(stm32.I2C_CR1_ACK)
|
||||
|
||||
if frameFirstAndLast == option || frameFirst == option || frameNoOption == option {
|
||||
// generate start condition
|
||||
i2c.Bus.CR1.SetBits(stm32.I2C_CR1_START)
|
||||
} else if false /* (hi2c->PreviousState == I2C_STATE_MASTER_BUSY_TX) */ {
|
||||
// generate restart condition
|
||||
i2c.Bus.CR1.SetBits(stm32.I2C_CR1_START)
|
||||
}
|
||||
|
||||
// ensure start bit is set
|
||||
if !i2c.waitForFlag(flagSB, true) {
|
||||
return errI2CSignalStartTimeout
|
||||
}
|
||||
|
||||
// send peripheral address
|
||||
switch addr.bitSize() {
|
||||
case 7: // 7-bit peripheral address
|
||||
i2c.Bus.DR.Set(addr.toRead())
|
||||
|
||||
case 10: // 10-bit peripheral address
|
||||
// TODO
|
||||
}
|
||||
|
||||
// wait for address ACK from peripheral
|
||||
if !i2c.waitForFlagOrError(flagADDR, true) {
|
||||
return errI2CSignalStartTimeout
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -20,15 +20,42 @@ type SPIConfig struct {
|
||||
}
|
||||
|
||||
// Configure is intended to setup the STM32 SPI1 interface.
|
||||
// Features still TODO:
|
||||
// - support SPI2 and SPI3
|
||||
// - allow setting data size to 16 bits?
|
||||
// - allow setting direction in HW for additional optimization?
|
||||
// - hardware SS pin?
|
||||
func (spi SPI) Configure(config SPIConfig) {
|
||||
|
||||
// -- CONFIGURING THE SPI IN MASTER MODE --
|
||||
//
|
||||
// 1. Select the BR[2:0] bits to define the serial clock baud rate (see
|
||||
// SPI_CR1 register).
|
||||
// 2. Select the CPOL and CPHA bits to define one of the four relationships
|
||||
// between the data transfer and the serial clock (see Figure 248). This
|
||||
// step is not required when the TI mode is selected.
|
||||
// 3. Set the DFF bit to define 8- or 16-bit data frame format
|
||||
// 4. Configure the LSBFIRST bit in the SPI_CR1 register to define the frame
|
||||
// format. This step is not required when the TI mode is selected.
|
||||
// 5. If the NSS pin is required in input mode, in hardware mode, connect the
|
||||
// NSS pin to a high-level signal during the complete byte transmit
|
||||
// sequence. In NSS software mode, set the SSM and SSI bits in the SPI_CR1
|
||||
// register. If the NSS pin is required in output mode, the SSOE bit only
|
||||
// should be set. This step is not required when the TI mode is selected.
|
||||
// 6. Set the FRF bit in SPI_CR2 to select the TI protocol for serial
|
||||
// communications.
|
||||
// 7. The MSTR and SPE bits must be set (they remain set only if the NSS pin
|
||||
// is connected to a high-level signal).
|
||||
|
||||
// disable SPI interface before any configuration changes
|
||||
spi.Bus.CR1.ClearBits(stm32.SPI_CR1_SPE)
|
||||
|
||||
// enable clock for SPI
|
||||
enableAltFuncClock(unsafe.Pointer(spi.Bus))
|
||||
|
||||
// init pins
|
||||
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
|
||||
}
|
||||
spi.configurePins(config)
|
||||
|
||||
// Get SPI baud rate based on the bus speed it's attached to
|
||||
var conf uint32 = spi.getBaudRate(config)
|
||||
|
||||
@@ -39,61 +66,72 @@ func (spi SPI) Configure(config SPIConfig) {
|
||||
|
||||
// set polarity and phase on the SPI interface
|
||||
switch config.Mode {
|
||||
case Mode0:
|
||||
conf &^= (1 << stm32.SPI_CR1_CPOL_Pos)
|
||||
conf &^= (1 << stm32.SPI_CR1_CPHA_Pos)
|
||||
case Mode1:
|
||||
conf &^= (1 << stm32.SPI_CR1_CPOL_Pos)
|
||||
conf |= (1 << stm32.SPI_CR1_CPHA_Pos)
|
||||
conf |= stm32.SPI_CR1_CPHA
|
||||
case Mode2:
|
||||
conf |= (1 << stm32.SPI_CR1_CPOL_Pos)
|
||||
conf &^= (1 << stm32.SPI_CR1_CPHA_Pos)
|
||||
conf |= stm32.SPI_CR1_CPOL
|
||||
case Mode3:
|
||||
conf |= (1 << stm32.SPI_CR1_CPOL_Pos)
|
||||
conf |= (1 << stm32.SPI_CR1_CPHA_Pos)
|
||||
default: // to mode 0
|
||||
conf &^= (1 << stm32.SPI_CR1_CPOL_Pos)
|
||||
conf &^= (1 << stm32.SPI_CR1_CPHA_Pos)
|
||||
conf |= stm32.SPI_CR1_CPOL
|
||||
conf |= stm32.SPI_CR1_CPHA
|
||||
}
|
||||
|
||||
// set to SPI controller
|
||||
conf |= stm32.SPI_CR1_MSTR
|
||||
// configure as SPI master
|
||||
conf |= stm32.SPI_CR1_MSTR | stm32.SPI_CR1_SSI
|
||||
|
||||
// disable MCU acting as SPI peripheral
|
||||
conf |= stm32.SPI_CR1_SSM | stm32.SPI_CR1_SSI
|
||||
// enable the SPI interface
|
||||
conf |= stm32.SPI_CR1_SPE
|
||||
|
||||
// use software CS (GPIO) by default
|
||||
conf |= stm32.SPI_CR1_SSM
|
||||
|
||||
// now set the configuration
|
||||
spi.Bus.CR1.Set(conf)
|
||||
|
||||
// init pins
|
||||
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
|
||||
}
|
||||
spi.configurePins(config)
|
||||
|
||||
// enable SPI interface
|
||||
spi.Bus.CR1.SetBits(stm32.SPI_CR1_SPE)
|
||||
spi.Bus.CR2.SetBits((conf & stm32.SPI_CR1_SSM_Msk) >> 16)
|
||||
}
|
||||
|
||||
// Transfer writes/reads a single byte using the SPI interface.
|
||||
func (spi SPI) Transfer(w byte) (byte, error) {
|
||||
// Write data to be transmitted to the SPI data register
|
||||
|
||||
// 1. Enable the SPI by setting the SPE bit to 1.
|
||||
// 2. Write the first data item to be transmitted into the SPI_DR register
|
||||
// (this clears the TXE flag).
|
||||
// 3. Wait until TXE=1 and write the second data item to be transmitted. Then
|
||||
// wait until RXNE=1 and read the SPI_DR to get the first received data
|
||||
// item (this clears the RXNE bit). Repeat this operation for each data
|
||||
// item to be transmitted/received until the n–1 received data.
|
||||
// 4. Wait until RXNE=1 and read the last received data.
|
||||
// 5. Wait until TXE=1 and then wait until BSY=0 before disabling the SPI.
|
||||
|
||||
// put output word (8-bit) in data register (DR), which is parallel-loaded
|
||||
// into shift register, and shifted out on MOSI.
|
||||
spi.Bus.DR.Set(uint32(w))
|
||||
|
||||
// Wait until transmit complete
|
||||
for !spi.Bus.SR.HasBits(stm32.SPI_SR_TXE) {
|
||||
}
|
||||
|
||||
// Wait until receive complete
|
||||
// wait for SPI bus receive buffer not empty bit (RXNE) to be set.
|
||||
// warning: blocks forever until this condition is met.
|
||||
for !spi.Bus.SR.HasBits(stm32.SPI_SR_RXNE) {
|
||||
}
|
||||
|
||||
// Wait until SPI is not busy
|
||||
// copy input word (8-bit) in data register (DR), which was shifted in on MISO
|
||||
// and parallel-loaded into register.
|
||||
data := byte(spi.Bus.DR.Get())
|
||||
|
||||
// wait for SPI bus transmit buffer empty bit (TXE) to be set.
|
||||
// warning: blocks forever until this condition is met.
|
||||
for !spi.Bus.SR.HasBits(stm32.SPI_SR_TXE) {
|
||||
}
|
||||
|
||||
// wait for SPI bus busy bit (BSY) to be clear to indicate synchronous
|
||||
// transfer complete. this will effectively prevent this Transfer() function
|
||||
// from being capable of maintaining high-bandwidth communication throughput,
|
||||
// but it will help guarantee stability on the bus.
|
||||
for spi.Bus.SR.HasBits(stm32.SPI_SR_BSY) {
|
||||
}
|
||||
|
||||
// clear the overrun flag (only in full-duplex mode)
|
||||
if !spi.Bus.CR1.HasBits(stm32.SPI_CR1_RXONLY | stm32.SPI_CR1_BIDIMODE | stm32.SPI_CR1_BIDIOE) {
|
||||
spi.Bus.SR.Get()
|
||||
}
|
||||
|
||||
// Return received data from SPI data register
|
||||
return byte(spi.Bus.DR.Get()), nil
|
||||
return data, nil
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ package machine
|
||||
|
||||
import (
|
||||
"device/stm32"
|
||||
"math/bits"
|
||||
"runtime/interrupt"
|
||||
)
|
||||
|
||||
@@ -46,8 +47,47 @@ type SPI struct {
|
||||
AltFuncSelector stm32.AltFunc
|
||||
}
|
||||
|
||||
func (spi SPI) configurePins(config SPIConfig) {}
|
||||
func (spi SPI) getBaudRate(config SPIConfig) uint32 { return 0 }
|
||||
func (spi SPI) configurePins(config SPIConfig) {
|
||||
config.SCK.ConfigureAltFunc(PinConfig{Mode: PinModeSPICLK}, spi.AltFuncSelector)
|
||||
config.SDO.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDO}, spi.AltFuncSelector)
|
||||
config.SDI.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDI}, spi.AltFuncSelector)
|
||||
}
|
||||
|
||||
func (spi SPI) getBaudRate(config SPIConfig) uint32 {
|
||||
var clock uint32
|
||||
switch spi.Bus {
|
||||
case stm32.SPI1:
|
||||
clock = CPUFrequency() / 2
|
||||
case stm32.SPI2, stm32.SPI3:
|
||||
clock = CPUFrequency() / 4
|
||||
}
|
||||
|
||||
// limit requested frequency to bus frequency and min frequency (DIV256)
|
||||
freq := config.Frequency
|
||||
if min := clock / 256; freq < min {
|
||||
freq = min
|
||||
} else if freq > clock {
|
||||
freq = clock
|
||||
}
|
||||
|
||||
// calculate the exact clock divisor (freq=clock/div -> div=clock/freq).
|
||||
// truncation is fine, since it produces a less-than-or-equal divisor, and
|
||||
// thus a greater-than-or-equal frequency.
|
||||
// divisors only come in consecutive powers of 2, so we can use log2 (or,
|
||||
// equivalently, bits.Len - 1) to convert to respective enum value.
|
||||
div := bits.Len32(clock/freq) - 1
|
||||
|
||||
// but DIV1 (2^0) is not permitted, as the least divisor is DIV2 (2^1), so
|
||||
// subtract 1 from the log2 value, keeping a lower bound of 0
|
||||
if div < 0 {
|
||||
div = 0
|
||||
} else if div > 0 {
|
||||
div--
|
||||
}
|
||||
|
||||
// finally, shift the enumerated value into position for SPI CR1
|
||||
return uint32(div) << stm32.SPI_CR1_BR_Pos
|
||||
}
|
||||
|
||||
// -- I2C ----------------------------------------------------------------------
|
||||
|
||||
@@ -55,3 +95,74 @@ type I2C struct {
|
||||
Bus *stm32.I2C_Type
|
||||
AltFuncSelector stm32.AltFunc
|
||||
}
|
||||
|
||||
func (i2c I2C) configurePins(config I2CConfig) {
|
||||
config.SCL.ConfigureAltFunc(PinConfig{Mode: PinModeI2CSCL}, i2c.AltFuncSelector)
|
||||
config.SDA.ConfigureAltFunc(PinConfig{Mode: PinModeI2CSDA}, i2c.AltFuncSelector)
|
||||
}
|
||||
|
||||
func (i2c I2C) getFreqRange(config I2CConfig) uint32 {
|
||||
// all I2C interfaces are on APB1 (42 MHz)
|
||||
clock := CPUFrequency() / 4
|
||||
// convert to MHz
|
||||
clock /= 1000000
|
||||
// must be between 2 MHz (or 4 MHz for fast mode (Fm)) and 50 MHz, inclusive
|
||||
var min, max uint32 = 2, 50
|
||||
if config.Frequency > 10000 {
|
||||
min = 4 // fast mode (Fm)
|
||||
}
|
||||
if clock < min {
|
||||
clock = min
|
||||
} else if clock > max {
|
||||
clock = max
|
||||
}
|
||||
return clock << stm32.I2C_CR2_FREQ_Pos
|
||||
}
|
||||
|
||||
func (i2c I2C) getRiseTime(config I2CConfig) uint32 {
|
||||
// These bits must be programmed with the maximum SCL rise time given in the
|
||||
// I2C bus specification, incremented by 1.
|
||||
// For instance: in Sm mode, the maximum allowed SCL rise time is 1000 ns.
|
||||
// If, in the I2C_CR2 register, the value of FREQ[5:0] bits is equal to 0x08
|
||||
// and PCLK1 = 125 ns, therefore the TRISE[5:0] bits must be programmed with
|
||||
// 09h (1000 ns / 125 ns = 8 + 1)
|
||||
freqRange := i2c.getFreqRange(config)
|
||||
if config.Frequency > 100000 {
|
||||
// fast mode (Fm) adjustment
|
||||
freqRange *= 300
|
||||
freqRange /= 1000
|
||||
}
|
||||
return (freqRange + 1) << stm32.I2C_TRISE_TRISE_Pos
|
||||
}
|
||||
|
||||
func (i2c I2C) getSpeed(config I2CConfig) uint32 {
|
||||
ccr := func(pclk uint32, freq uint32, coeff uint32) uint32 {
|
||||
return (((pclk - 1) / (freq * coeff)) + 1) & stm32.I2C_CCR_CCR_Msk
|
||||
}
|
||||
sm := func(pclk uint32, freq uint32) uint32 { // standard mode (Sm)
|
||||
if s := ccr(pclk, freq, 2); s < 4 {
|
||||
return 4
|
||||
} else {
|
||||
return s
|
||||
}
|
||||
}
|
||||
fm := func(pclk uint32, freq uint32, duty uint8) uint32 { // fast mode (Fm)
|
||||
if duty == DutyCycle2 {
|
||||
return ccr(pclk, freq, 3)
|
||||
} else {
|
||||
return ccr(pclk, freq, 25) | stm32.I2C_CCR_DUTY
|
||||
}
|
||||
}
|
||||
// all I2C interfaces are on APB1 (42 MHz)
|
||||
clock := CPUFrequency() / 4
|
||||
if config.Frequency <= 100000 {
|
||||
return sm(clock, config.Frequency)
|
||||
} else {
|
||||
s := fm(clock, config.Frequency, config.DutyCycle)
|
||||
if (s & stm32.I2C_CCR_CCR_Msk) == 0 {
|
||||
return 1
|
||||
} else {
|
||||
return s | stm32.I2C_CCR_F_S
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ func gosched()
|
||||
|
||||
// PutcharUART writes a byte to the UART synchronously, without using interrupts
|
||||
// or calling the scheduler
|
||||
func PutcharUART(u UART, c byte) {
|
||||
func PutcharUART(u *UART, c byte) {
|
||||
// ensure the UART has been configured
|
||||
if !u.SCGC.HasBits(u.SCGCMask) {
|
||||
u.configure(UARTConfig{}, false)
|
||||
@@ -79,15 +79,13 @@ func PutcharUART(u UART, c byte) {
|
||||
|
||||
// PollUART manually checks a UART status and calls the ISR. This should only be
|
||||
// called by runtime.abort.
|
||||
func PollUART(u UART) {
|
||||
func PollUART(u *UART) {
|
||||
if u.SCGC.HasBits(u.SCGCMask) {
|
||||
u.handleStatusInterrupt(u.Interrupt)
|
||||
}
|
||||
}
|
||||
|
||||
type UART = *UARTData
|
||||
|
||||
type UARTData struct {
|
||||
type UART struct {
|
||||
*nxp.UART_Type
|
||||
SCGC *volatile.Register32
|
||||
SCGCMask uint32
|
||||
@@ -103,11 +101,11 @@ type UARTData struct {
|
||||
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}
|
||||
var UART0 = UART{UART_Type: nxp.UART0, SCGC: &nxp.SIM.SCGC4, SCGCMask: nxp.SIM_SCGC4_UART0, DefaultRX: defaultUART0RX, DefaultTX: defaultUART0TX}
|
||||
var UART1 = UART{UART_Type: nxp.UART1, SCGC: &nxp.SIM.SCGC4, SCGCMask: nxp.SIM_SCGC4_UART1, DefaultRX: defaultUART1RX, DefaultTX: defaultUART1TX}
|
||||
var UART2 = UART{UART_Type: nxp.UART2, SCGC: &nxp.SIM.SCGC4, SCGCMask: nxp.SIM_SCGC4_UART2, DefaultRX: defaultUART2RX, DefaultTX: defaultUART2TX}
|
||||
var UART3 = UART{UART_Type: nxp.UART3, SCGC: &nxp.SIM.SCGC4, SCGCMask: nxp.SIM_SCGC4_UART3, DefaultRX: defaultUART3RX, DefaultTX: defaultUART3TX}
|
||||
var UART4 = UART{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)
|
||||
@@ -118,11 +116,11 @@ func init() {
|
||||
}
|
||||
|
||||
// Configure the UART.
|
||||
func (u UART) Configure(config UARTConfig) {
|
||||
func (u *UART) Configure(config UARTConfig) {
|
||||
u.configure(config, true)
|
||||
}
|
||||
|
||||
func (u UART) configure(config UARTConfig, canSched bool) {
|
||||
func (u *UART) configure(config UARTConfig, canSched bool) {
|
||||
// from: serial_begin
|
||||
|
||||
if !u.Configured {
|
||||
@@ -183,7 +181,7 @@ func (u UART) configure(config UARTConfig, canSched bool) {
|
||||
}
|
||||
}
|
||||
|
||||
func (u UART) Disable() {
|
||||
func (u *UART) Disable() {
|
||||
// from: serial_end
|
||||
|
||||
// check if the device has been enabled already
|
||||
@@ -206,13 +204,13 @@ func (u UART) Disable() {
|
||||
u.Buffer.Clear()
|
||||
}
|
||||
|
||||
func (u UART) Flush() {
|
||||
func (u *UART) Flush() {
|
||||
for u.Transmitting.Get() != 0 {
|
||||
gosched()
|
||||
}
|
||||
}
|
||||
|
||||
func (u UART) handleStatusInterrupt(interrupt.Interrupt) {
|
||||
func (u *UART) handleStatusInterrupt(interrupt.Interrupt) {
|
||||
// from: uart0_status_isr
|
||||
|
||||
// receive
|
||||
@@ -290,7 +288,7 @@ func (u UART) handleStatusInterrupt(interrupt.Interrupt) {
|
||||
}
|
||||
|
||||
// WriteByte writes a byte of data to the UART.
|
||||
func (u UART) WriteByte(c byte) error {
|
||||
func (u *UART) WriteByte(c byte) error {
|
||||
if !u.Configured {
|
||||
return ErrNotConfigured
|
||||
}
|
||||
|
||||
@@ -3,3 +3,7 @@ package os
|
||||
func Getenv(key string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func LookupEnv(key string) (string, bool) {
|
||||
return "", false
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// +build darwin linux,!baremetal freebsd,!baremetal
|
||||
// +build darwin linux,!baremetal,!wasi freebsd,!baremetal
|
||||
|
||||
package os
|
||||
|
||||
|
||||
+36
-1
@@ -1,5 +1,40 @@
|
||||
package reflect
|
||||
|
||||
import "unsafe"
|
||||
|
||||
// Some of code here has been copied from the Go sources:
|
||||
// https://github.com/golang/go/blob/go1.15.2/src/reflect/swapper.go
|
||||
// It has the following copyright note:
|
||||
//
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
func Swapper(slice interface{}) func(i, j int) {
|
||||
panic("unimplemented: reflect.Swapper")
|
||||
v := ValueOf(slice)
|
||||
if v.Kind() != Slice {
|
||||
panic(&ValueError{Method: "Swapper"})
|
||||
}
|
||||
|
||||
// Just return Nop func if nothing to swap.
|
||||
if v.Len() < 2 {
|
||||
return func(i, j int) {}
|
||||
}
|
||||
|
||||
typ := v.Type().Elem()
|
||||
size := typ.Size()
|
||||
|
||||
header := (*SliceHeader)(v.value)
|
||||
tmp := unsafe.Pointer(&make([]byte, size)[0])
|
||||
|
||||
return func(i, j int) {
|
||||
if uint(i) >= uint(header.Len) || uint(j) >= uint(header.Len) {
|
||||
panic("reflect: slice index out of range")
|
||||
}
|
||||
val1 := unsafe.Pointer(header.Data + uintptr(i)*size)
|
||||
val2 := unsafe.Pointer(header.Data + uintptr(j)*size)
|
||||
memcpy(tmp, val1, size)
|
||||
memcpy(val1, val2, size)
|
||||
memcpy(val2, tmp, size)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package runtime
|
||||
|
||||
import "device"
|
||||
|
||||
const GOARCH = "386"
|
||||
|
||||
// The bitness of the CPU (e.g. 8, 32, 64).
|
||||
@@ -10,4 +12,6 @@ func align(ptr uintptr) uintptr {
|
||||
return (ptr + 3) &^ 3
|
||||
}
|
||||
|
||||
func getCurrentStackPointer() uintptr
|
||||
func getCurrentStackPointer() uintptr {
|
||||
return device.AsmFull("movl %esp, {}", nil)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package runtime
|
||||
|
||||
import "device"
|
||||
|
||||
const GOARCH = "amd64"
|
||||
|
||||
// The bitness of the CPU (e.g. 8, 32, 64).
|
||||
@@ -12,4 +14,6 @@ func align(ptr uintptr) uintptr {
|
||||
return (ptr + 15) &^ 15
|
||||
}
|
||||
|
||||
func getCurrentStackPointer() uintptr
|
||||
func getCurrentStackPointer() uintptr {
|
||||
return device.AsmFull("movq %rsp, {}", nil)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// +build arm,!baremetal arm,arm7tdmi
|
||||
// +build arm,!baremetal,!wasm arm,arm7tdmi
|
||||
|
||||
package runtime
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package runtime
|
||||
|
||||
import "device/arm"
|
||||
|
||||
const GOARCH = "arm64"
|
||||
|
||||
// The bitness of the CPU (e.g. 8, 32, 64).
|
||||
@@ -9,5 +11,6 @@ const TargetBits = 64
|
||||
func align(ptr uintptr) uintptr {
|
||||
return (ptr + 7) &^ 7
|
||||
}
|
||||
|
||||
func getCurrentStackPointer() uintptr
|
||||
func getCurrentStackPointer() uintptr {
|
||||
return arm.AsmFull("mov {}, sp", nil)
|
||||
}
|
||||
|
||||
@@ -39,4 +39,9 @@ func libc_free(ptr unsafe.Pointer) {
|
||||
free(ptr)
|
||||
}
|
||||
|
||||
//go:linkname syscall_Exit syscall.Exit
|
||||
func syscall_Exit(code int) {
|
||||
abort()
|
||||
}
|
||||
|
||||
const baremetal = true
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
// +build !scheduler.none
|
||||
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"internal/task"
|
||||
"sync/atomic"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// notifiedPlaceholder is a placeholder task which is used to indicate that the condition variable has been notified.
|
||||
var notifiedPlaceholder task.Task
|
||||
|
||||
// Cond is a simplified condition variable, useful for notifying goroutines of interrupts.
|
||||
type Cond struct {
|
||||
t *task.Task
|
||||
}
|
||||
|
||||
// Notify sends a notification.
|
||||
// If the condition variable already has a pending notification, this returns false.
|
||||
func (c *Cond) Notify() bool {
|
||||
for {
|
||||
t := (*task.Task)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&c.t))))
|
||||
switch t {
|
||||
case nil:
|
||||
// Nothing is waiting yet.
|
||||
// Apply the notification placeholder.
|
||||
if atomic.CompareAndSwapPointer((*unsafe.Pointer)(unsafe.Pointer(&c.t)), unsafe.Pointer(t), unsafe.Pointer(¬ifiedPlaceholder)) {
|
||||
return true
|
||||
}
|
||||
case ¬ifiedPlaceholder:
|
||||
// The condition variable has already been notified.
|
||||
return false
|
||||
default:
|
||||
// Unblock the waiting task.
|
||||
if atomic.CompareAndSwapPointer((*unsafe.Pointer)(unsafe.Pointer(&c.t)), unsafe.Pointer(t), nil) {
|
||||
runqueuePushBack(t)
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Poll checks for a notification.
|
||||
// If a notification is found, it is cleared and this returns true.
|
||||
func (c *Cond) Poll() bool {
|
||||
for {
|
||||
t := (*task.Task)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&c.t))))
|
||||
switch t {
|
||||
case nil:
|
||||
// No notifications are present.
|
||||
return false
|
||||
case ¬ifiedPlaceholder:
|
||||
// A notification arrived and there is no waiting goroutine.
|
||||
// Clear the notification and return.
|
||||
if atomic.CompareAndSwapPointer((*unsafe.Pointer)(unsafe.Pointer(&c.t)), unsafe.Pointer(t), nil) {
|
||||
return true
|
||||
}
|
||||
default:
|
||||
// A task is blocked on the condition variable, which means it has not been notified.
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for a notification.
|
||||
// If the condition variable was previously notified, this returns immediately.
|
||||
func (c *Cond) Wait() {
|
||||
cur := task.Current()
|
||||
for {
|
||||
t := (*task.Task)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&c.t))))
|
||||
switch t {
|
||||
case nil:
|
||||
// Condition variable has not been notified.
|
||||
// Block the current task on the condition variable.
|
||||
if atomic.CompareAndSwapPointer((*unsafe.Pointer)(unsafe.Pointer(&c.t)), nil, unsafe.Pointer(cur)) {
|
||||
task.Pause()
|
||||
return
|
||||
}
|
||||
case ¬ifiedPlaceholder:
|
||||
// A notification arrived and there is no waiting goroutine.
|
||||
// Clear the notification and return.
|
||||
if atomic.CompareAndSwapPointer((*unsafe.Pointer)(unsafe.Pointer(&c.t)), unsafe.Pointer(t), nil) {
|
||||
return
|
||||
}
|
||||
default:
|
||||
panic("interrupt.Cond: condition variable in use by another goroutine")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
// +build scheduler.none
|
||||
|
||||
package runtime
|
||||
|
||||
import "runtime/interrupt"
|
||||
|
||||
// Cond is a simplified condition variable, useful for notifying goroutines of interrupts.
|
||||
type Cond struct {
|
||||
notified bool
|
||||
}
|
||||
|
||||
// Notify sends a notification.
|
||||
// If the condition variable already has a pending notification, this returns false.
|
||||
func (c *Cond) Notify() bool {
|
||||
i := interrupt.Disable()
|
||||
prev := c.notified
|
||||
c.notified = true
|
||||
interrupt.Restore(i)
|
||||
return !prev
|
||||
}
|
||||
|
||||
// Poll checks for a notification.
|
||||
// If a notification is found, it is cleared and this returns true.
|
||||
func (c *Cond) Poll() bool {
|
||||
i := interrupt.Disable()
|
||||
notified := c.notified
|
||||
c.notified = false
|
||||
interrupt.Restore(i)
|
||||
return notified
|
||||
}
|
||||
|
||||
// Wait for a notification.
|
||||
// If the condition variable was previously notified, this returns immediately.
|
||||
func (c *Cond) Wait() {
|
||||
for !c.Poll() {
|
||||
waitForEvents()
|
||||
}
|
||||
}
|
||||
@@ -59,8 +59,15 @@ func dynamicLoader(base uintptr, dyn *dyn64) {
|
||||
for relasz > 0 && rela != nil {
|
||||
switch rela.Info {
|
||||
case rAARCH64_RELATIVE:
|
||||
if debugLoader {
|
||||
println("relocating ", uintptr(rela.Addend), " to ", base+uintptr(rela.Addend))
|
||||
}
|
||||
ptr := (*uint64)(unsafe.Pointer(base + uintptr(rela.Off)))
|
||||
*ptr = uint64(base + uintptr(rela.Addend))
|
||||
default:
|
||||
if debugLoader {
|
||||
println("unknown section to load:", rela.Info)
|
||||
}
|
||||
}
|
||||
|
||||
rptr := uintptr(unsafe.Pointer(rela))
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
.section .text.tinygo_scanCurrentStack
|
||||
.global tinygo_scanCurrentStack
|
||||
.type tinygo_scanCurrentStack, %function
|
||||
tinygo_scanCurrentStack:
|
||||
// Sources:
|
||||
// * https://stackoverflow.com/questions/18024672/what-registers-are-preserved-through-a-linux-x86-64-function-call
|
||||
// * https://godbolt.org/z/q7e8dn
|
||||
|
||||
// Save callee-saved registers.
|
||||
pushl %ebx
|
||||
pushl %esi
|
||||
pushl %edi
|
||||
pushl %ebp
|
||||
|
||||
// Scan the stack.
|
||||
pushl %esp
|
||||
calll tinygo_scanstack
|
||||
|
||||
// Restore the stack pointer. Registers do not need to be restored as they
|
||||
// were only pushed to be discoverable by the GC.
|
||||
addl $20, %esp
|
||||
retl
|
||||
@@ -0,0 +1,29 @@
|
||||
#ifdef __ELF__
|
||||
.section .text.tinygo_scanCurrentStack
|
||||
.global tinygo_scanCurrentStack
|
||||
tinygo_scanCurrentStack:
|
||||
#else // Darwin
|
||||
.global _tinygo_scanCurrentStack
|
||||
_tinygo_scanCurrentStack:
|
||||
#endif
|
||||
// Save callee-saved registers.
|
||||
pushq %rbx
|
||||
pushq %rbp
|
||||
pushq %r12
|
||||
pushq %r13
|
||||
pushq %r14
|
||||
pushq %r15
|
||||
|
||||
// Scan the stack.
|
||||
subq $8, %rsp // adjust the stack before the call to maintain 16-byte alignment
|
||||
movq %rsp, %rdi
|
||||
#ifdef __ELF__
|
||||
callq tinygo_scanstack
|
||||
#else
|
||||
callq _tinygo_scanstack // Darwin
|
||||
#endif
|
||||
|
||||
// Restore the stack pointer. Registers do not need to be restored as they
|
||||
// were only pushed to be discoverable by the GC.
|
||||
addq $56, %rsp
|
||||
retq
|
||||
@@ -1,14 +1,25 @@
|
||||
// Only generate .debug_frame, don't generate .eh_frame.
|
||||
.cfi_sections .debug_frame
|
||||
|
||||
.section .text.tinygo_scanCurrentStack
|
||||
.global tinygo_scanCurrentStack
|
||||
.type tinygo_scanCurrentStack, %function
|
||||
tinygo_scanCurrentStack:
|
||||
.cfi_startproc
|
||||
// Save callee-saved registers onto the stack.
|
||||
#if defined(__thumb2__)
|
||||
push {r4-r11, lr}
|
||||
.cfi_def_cfa_offset 9*4
|
||||
#else
|
||||
mov r0, r8
|
||||
mov r1, r9
|
||||
mov r2, r10
|
||||
mov r3, r11
|
||||
push {r0-r3, lr}
|
||||
.cfi_def_cfa_offset 5*4
|
||||
push {r4-r7}
|
||||
.cfi_def_cfa_offset 4*4
|
||||
#endif
|
||||
|
||||
// Scan the stack.
|
||||
mov r0, sp
|
||||
@@ -16,4 +27,7 @@ tinygo_scanCurrentStack:
|
||||
|
||||
// Restore stack state and return.
|
||||
add sp, #32
|
||||
.cfi_def_cfa_offset 1*4
|
||||
pop {pc}
|
||||
.cfi_endproc
|
||||
.size tinygo_scanCurrentStack, .-tinygo_scanCurrentStack
|
||||
@@ -0,0 +1,23 @@
|
||||
.section .text.tinygo_scanCurrentStack
|
||||
.global tinygo_scanCurrentStack
|
||||
.type tinygo_scanCurrentStack, %function
|
||||
tinygo_scanCurrentStack:
|
||||
// Sources:
|
||||
// * https://developer.arm.com/architectures/learn-the-architecture/armv8-a-instruction-set-architecture/procedure-call-standard
|
||||
// * https://godbolt.org/z/qrvrEh
|
||||
|
||||
// Save callee-saved registers.
|
||||
stp x29, x30, [sp, #-96]!
|
||||
stp x28, x27, [sp, #16]
|
||||
stp x26, x25, [sp, #32]
|
||||
stp x24, x23, [sp, #48]
|
||||
stp x22, x21, [sp, #64]
|
||||
stp x20, x19, [sp, #80]
|
||||
|
||||
// Scan the stack.
|
||||
mov x0, sp
|
||||
bl tinygo_scanstack
|
||||
|
||||
// Restore stack state and return.
|
||||
ldp x29, x30, [sp], #96
|
||||
ret
|
||||
@@ -0,0 +1,52 @@
|
||||
.section .text.tinygo_scanCurrentStack
|
||||
.global tinygo_scanCurrentStack
|
||||
.type tinygo_scanCurrentStack, %function
|
||||
tinygo_scanCurrentStack:
|
||||
// Save callee-saved registers.
|
||||
push r29 // Y
|
||||
push r28 // Y
|
||||
push r17
|
||||
push r16
|
||||
push r15
|
||||
push r14
|
||||
push r13
|
||||
push r12
|
||||
push r11
|
||||
push r10
|
||||
push r9
|
||||
push r8
|
||||
push r7
|
||||
push r6
|
||||
push r5
|
||||
push r4
|
||||
push r3
|
||||
push r2
|
||||
|
||||
// Scan the stack.
|
||||
in r24, 0x3d; SPL
|
||||
in r25, 0x3e; SPH
|
||||
#if __AVR_ARCH__ == 2 || __AVR_ARCH__ == 25
|
||||
rcall tinygo_scanstack
|
||||
#else
|
||||
call tinygo_scanstack
|
||||
#endif
|
||||
|
||||
// Restore callee-saved registers.
|
||||
pop r2
|
||||
pop r3
|
||||
pop r4
|
||||
pop r5
|
||||
pop r6
|
||||
pop r7
|
||||
pop r8
|
||||
pop r9
|
||||
pop r10
|
||||
pop r11
|
||||
pop r12
|
||||
pop r13
|
||||
pop r14
|
||||
pop r15
|
||||
pop r16
|
||||
pop r17
|
||||
pop r28 // Y
|
||||
pop r29 // Y
|
||||
@@ -1,5 +1,5 @@
|
||||
// +build gc.conservative gc.extalloc
|
||||
// +build !baremetal
|
||||
// +build wasm
|
||||
|
||||
package runtime
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// +build gc.conservative gc.extalloc
|
||||
// +build baremetal
|
||||
// +build !wasm
|
||||
|
||||
package runtime
|
||||
|
||||
|
||||
@@ -261,6 +261,13 @@ func hashmapDelete(m *hashmap, key unsafe.Pointer, hash uint32, keyEqual func(x,
|
||||
// Iterate over a hashmap.
|
||||
//go:nobounds
|
||||
func hashmapNext(m *hashmap, it *hashmapIterator, key, value unsafe.Pointer) bool {
|
||||
if m == nil {
|
||||
// Iterating over a nil slice appears to be allowed by the Go spec:
|
||||
// https://groups.google.com/g/golang-nuts/c/gVgVLQU1FFE?pli=1
|
||||
// https://play.golang.org/p/S8jxAMytKDB
|
||||
return false
|
||||
}
|
||||
|
||||
numBuckets := uintptr(1) << m.bucketBits
|
||||
for {
|
||||
if it.bucketIndex >= 8 {
|
||||
|
||||
+83
-3
@@ -98,10 +98,90 @@ func printint64(n int64) {
|
||||
printuint64(uint64(n))
|
||||
}
|
||||
|
||||
// printfloat32() was copied from the relevant source in the original Go
|
||||
// implementation and modified to work with float32 instead of float64. It is
|
||||
// copyright by the Go authors, licensed under the same BSD 3-clause license.
|
||||
// See https://golang.org/LICENSE for details.
|
||||
//
|
||||
// It is a near-duplicate of printfloat64. This is done so that printing a
|
||||
// float32 value doesn't involve float64 routines, which can be unexpected and a
|
||||
// problem sometimes. It comes with a possible code size reduction if both
|
||||
// printfloat32 and printfloat64 are used, which seems uncommon.
|
||||
//
|
||||
// Source:
|
||||
// https://github.com/golang/go/blob/master/src/runtime/print.go
|
||||
func printfloat32(v float32) {
|
||||
// TODO: write an implementation like printfloat64, as some systems have
|
||||
// 32-bit floats but only software emulation for 64-bit floats.
|
||||
printfloat64(float64(v))
|
||||
switch {
|
||||
case v != v:
|
||||
printstring("NaN")
|
||||
return
|
||||
case v+v == v && v > 0:
|
||||
printstring("+Inf")
|
||||
return
|
||||
case v+v == v && v < 0:
|
||||
printstring("-Inf")
|
||||
return
|
||||
}
|
||||
|
||||
const n = 7 // digits printed
|
||||
var buf [n + 7]byte
|
||||
buf[0] = '+'
|
||||
e := 0 // exp
|
||||
if v == 0 {
|
||||
if 1/v < 0 {
|
||||
buf[0] = '-'
|
||||
}
|
||||
} else {
|
||||
if v < 0 {
|
||||
v = -v
|
||||
buf[0] = '-'
|
||||
}
|
||||
|
||||
// normalize
|
||||
for v >= 10 {
|
||||
e++
|
||||
v /= 10
|
||||
}
|
||||
for v < 1 {
|
||||
e--
|
||||
v *= 10
|
||||
}
|
||||
|
||||
// round
|
||||
h := float32(5.0)
|
||||
for i := 0; i < n; i++ {
|
||||
h /= 10
|
||||
}
|
||||
v += h
|
||||
if v >= 10 {
|
||||
e++
|
||||
v /= 10
|
||||
}
|
||||
}
|
||||
|
||||
// format +d.dddd+edd
|
||||
for i := 0; i < n; i++ {
|
||||
s := int(v)
|
||||
buf[i+2] = byte(s + '0')
|
||||
v -= float32(s)
|
||||
v *= 10
|
||||
}
|
||||
buf[1] = buf[2]
|
||||
buf[2] = '.'
|
||||
|
||||
buf[n+2] = 'e'
|
||||
buf[n+3] = '+'
|
||||
if e < 0 {
|
||||
e = -e
|
||||
buf[n+3] = '-'
|
||||
}
|
||||
|
||||
buf[n+4] = byte(e/100) + '0'
|
||||
buf[n+5] = byte(e/10)%10 + '0'
|
||||
buf[n+6] = byte(e%10) + '0'
|
||||
for _, c := range buf {
|
||||
putchar(c)
|
||||
}
|
||||
}
|
||||
|
||||
// printfloat64() was copied from the relevant source in the original Go
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// +build cortexm,!nxp
|
||||
// +build cortexm,!nxp,!qemu
|
||||
|
||||
package runtime
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// +build cortexm,!nxp
|
||||
// +build atsamd21 nrf51
|
||||
|
||||
package runtime
|
||||
|
||||
|
||||
@@ -1,14 +1,19 @@
|
||||
// +build nxp
|
||||
// +build cortexm,!atsamd21,!nrf51
|
||||
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"device/nxp"
|
||||
"device/arm"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
SystemControl_CFSR_KnownFault = nxp.SystemControl_CFSR_IACCVIOL | nxp.SystemControl_CFSR_DACCVIOL | nxp.SystemControl_CFSR_MUNSTKERR | nxp.SystemControl_CFSR_MSTKERR | nxp.SystemControl_CFSR_MLSPERR | nxp.SystemControl_CFSR_IBUSERR | nxp.SystemControl_CFSR_PRECISERR | nxp.SystemControl_CFSR_IMPRECISERR | nxp.SystemControl_CFSR_UNSTKERR | nxp.SystemControl_CFSR_STKERR | nxp.SystemControl_CFSR_LSPERR | nxp.SystemControl_CFSR_UNDEFINSTR | nxp.SystemControl_CFSR_INVSTATE | nxp.SystemControl_CFSR_INVPC | nxp.SystemControl_CFSR_NOCP | nxp.SystemControl_CFSR_UNALIGNED | nxp.SystemControl_CFSR_DIVBYZERO
|
||||
SCB_CFSR_KnownFault = arm.SCB_CFSR_IACCVIOL | arm.SCB_CFSR_DACCVIOL |
|
||||
arm.SCB_CFSR_MUNSTKERR | arm.SCB_CFSR_MSTKERR | arm.SCB_CFSR_MLSPERR |
|
||||
arm.SCB_CFSR_IBUSERR | arm.SCB_CFSR_PRECISERR | arm.SCB_CFSR_IMPRECISERR |
|
||||
arm.SCB_CFSR_UNSTKERR | arm.SCB_CFSR_STKERR | arm.SCB_CFSR_LSPERR |
|
||||
arm.SCB_CFSR_UNDEFINSTR | arm.SCB_CFSR_INVSTATE | arm.SCB_CFSR_INVPC |
|
||||
arm.SCB_CFSR_NOCP | arm.SCB_CFSR_UNALIGNED | arm.SCB_CFSR_DIVBYZERO
|
||||
)
|
||||
|
||||
// See runtime_cortexm_hardfault.go
|
||||
@@ -104,7 +109,9 @@ func handleHardFault(sp *interruptStack) {
|
||||
|
||||
// GetFaultStatus reads the System Control Block Configurable Fault Status
|
||||
// Register and returns it as a FaultStatus.
|
||||
func GetFaultStatus() FaultStatus { return FaultStatus(nxp.SystemControl.CFSR.Get()) }
|
||||
func GetFaultStatus() FaultStatus {
|
||||
return FaultStatus(arm.SCB.CFSR.Get())
|
||||
}
|
||||
|
||||
type FaultStatus uint32
|
||||
type MemFaultStatus uint32
|
||||
@@ -116,7 +123,9 @@ func (fs FaultStatus) Bus() BusFaultStatus { return BusFaultStatus(fs) }
|
||||
func (fs FaultStatus) Usage() UsageFaultStatus { return UsageFaultStatus(fs) }
|
||||
|
||||
// Unknown returns true if the cause of the fault is not know
|
||||
func (fs FaultStatus) Unknown() bool { return fs&SystemControl_CFSR_KnownFault == 0 }
|
||||
func (fs FaultStatus) Unknown() bool {
|
||||
return fs&SCB_CFSR_KnownFault == 0
|
||||
}
|
||||
|
||||
// InstructionAccessViolation: the processor attempted an instruction fetch from
|
||||
// a location that does not permit execution
|
||||
@@ -128,7 +137,7 @@ func (fs FaultStatus) Unknown() bool { return fs&SystemControl_CFSR_KnownFault =
|
||||
// the faulting instruction. The processor has not written a fault address to
|
||||
// the MMAR."
|
||||
func (fs MemFaultStatus) InstructionAccessViolation() bool {
|
||||
return fs&nxp.SystemControl_CFSR_IACCVIOL != 0
|
||||
return fs&arm.SCB_CFSR_IACCVIOL != 0
|
||||
}
|
||||
|
||||
// DataAccessViolation: the processor attempted a load or store at a location
|
||||
@@ -137,7 +146,9 @@ func (fs MemFaultStatus) InstructionAccessViolation() bool {
|
||||
// "When this bit is 1, the PC value stacked for the exception return points to
|
||||
// the faulting instruction. The processor has loaded the MMAR with the address
|
||||
// of the attempted access."
|
||||
func (fs MemFaultStatus) DataAccessViolation() bool { return fs&nxp.SystemControl_CFSR_DACCVIOL != 0 }
|
||||
func (fs MemFaultStatus) DataAccessViolation() bool {
|
||||
return fs&arm.SCB_CFSR_DACCVIOL != 0
|
||||
}
|
||||
|
||||
// WhileUnstackingException: unstack for an exception return has caused one or
|
||||
// more access violations
|
||||
@@ -147,7 +158,7 @@ func (fs MemFaultStatus) DataAccessViolation() bool { return fs&nxp.SystemContro
|
||||
// the SP from the failing return, and has not performed a new save. The
|
||||
// processor has not written a fault address to the MMAR."
|
||||
func (fs MemFaultStatus) WhileUnstackingException() bool {
|
||||
return fs&nxp.SystemControl_CFSR_MUNSTKERR != 0
|
||||
return fs&arm.SCB_CFSR_MUNSTKERR != 0
|
||||
}
|
||||
|
||||
// WileStackingException: stacking for an exception entry has caused one or more
|
||||
@@ -156,11 +167,15 @@ func (fs MemFaultStatus) WhileUnstackingException() bool {
|
||||
// "When this bit is 1, the SP is still adjusted but the values in the context
|
||||
// area on the stack might be incorrect. The processor has not written a fault
|
||||
// address to the MMAR."
|
||||
func (fs MemFaultStatus) WileStackingException() bool { return fs&nxp.SystemControl_CFSR_MSTKERR != 0 }
|
||||
func (fs MemFaultStatus) WileStackingException() bool {
|
||||
return fs&arm.SCB_CFSR_MSTKERR != 0
|
||||
}
|
||||
|
||||
// DuringFPLazyStatePres: A MemManage fault occurred during floating-point lazy
|
||||
// state preservation
|
||||
func (fs MemFaultStatus) DuringFPLazyStatePres() bool { return fs&nxp.SystemControl_CFSR_MLSPERR != 0 }
|
||||
func (fs MemFaultStatus) DuringFPLazyStatePres() bool {
|
||||
return fs&arm.SCB_CFSR_MLSPERR != 0
|
||||
}
|
||||
|
||||
// InstructionBusError: instruction bus error
|
||||
//
|
||||
@@ -170,11 +185,15 @@ func (fs MemFaultStatus) DuringFPLazyStatePres() bool { return fs&nxp.SystemCont
|
||||
//
|
||||
// When the processor sets this bit is 1, it does not write a fault address to
|
||||
// the BFAR."
|
||||
func (fs BusFaultStatus) InstructionBusError() bool { return fs&nxp.SystemControl_CFSR_IBUSERR != 0 }
|
||||
func (fs BusFaultStatus) InstructionBusError() bool {
|
||||
return fs&arm.SCB_CFSR_IBUSERR != 0
|
||||
}
|
||||
|
||||
// PreciseDataBusError: a data bus error has occurred, and the PC value stacked
|
||||
// for the exception return points to the instruction that caused the fault
|
||||
func (fs BusFaultStatus) PreciseDataBusError() bool { return fs&nxp.SystemControl_CFSR_PRECISERR != 0 }
|
||||
func (fs BusFaultStatus) PreciseDataBusError() bool {
|
||||
return fs&arm.SCB_CFSR_PRECISERR != 0
|
||||
}
|
||||
|
||||
// ImpreciseDataBusError: a data bus error has occurred, but the return address
|
||||
// in the stack frame is not related to the instruction that caused the error
|
||||
@@ -189,7 +208,7 @@ func (fs BusFaultStatus) PreciseDataBusError() bool { return fs&nxp.SystemContro
|
||||
// enters the handler for the imprecise BusFault, the handler detects both
|
||||
// IMPRECISERR set to 1 and one of the precise fault status bits set to 1."
|
||||
func (fs BusFaultStatus) ImpreciseDataBusError() bool {
|
||||
return fs&nxp.SystemControl_CFSR_IMPRECISERR != 0
|
||||
return fs&arm.SCB_CFSR_IMPRECISERR != 0
|
||||
}
|
||||
|
||||
// WhileUnstackingException: unstack for an exception return has caused one or
|
||||
@@ -200,7 +219,7 @@ func (fs BusFaultStatus) ImpreciseDataBusError() bool {
|
||||
// does not adjust the SP from the failing return, does not performed a new
|
||||
// save, and does not write a fault address to the BFAR."
|
||||
func (fs BusFaultStatus) WhileUnstackingException() bool {
|
||||
return fs&nxp.SystemControl_CFSR_UNSTKERR != 0
|
||||
return fs&arm.SCB_CFSR_UNSTKERR != 0
|
||||
}
|
||||
|
||||
// WhileStackingException: stacking for an exception entry has caused one or
|
||||
@@ -209,11 +228,15 @@ func (fs BusFaultStatus) WhileUnstackingException() bool {
|
||||
// "When the processor sets this bit to 1, the SP is still adjusted but the
|
||||
// values in the context area on the stack might be incorrect. The processor
|
||||
// does not write a fault address to the BFAR."
|
||||
func (fs BusFaultStatus) WhileStackingException() bool { return fs&nxp.SystemControl_CFSR_STKERR != 0 }
|
||||
func (fs BusFaultStatus) WhileStackingException() bool {
|
||||
return fs&arm.SCB_CFSR_STKERR != 0
|
||||
}
|
||||
|
||||
// DuringFPLazyStatePres: A bus fault occurred during floating-point lazy state
|
||||
// preservation
|
||||
func (fs BusFaultStatus) DuringFPLazyStatePres() bool { return fs&nxp.SystemControl_CFSR_LSPERR != 0 }
|
||||
func (fs BusFaultStatus) DuringFPLazyStatePres() bool {
|
||||
return fs&arm.SCB_CFSR_LSPERR != 0
|
||||
}
|
||||
|
||||
// UndefinedInstruction: the processor has attempted to execute an undefined
|
||||
// instruction
|
||||
@@ -223,7 +246,7 @@ func (fs BusFaultStatus) DuringFPLazyStatePres() bool { return fs&nxp.SystemCont
|
||||
//
|
||||
// An undefined instruction is an instruction that the processor cannot decode."
|
||||
func (fs UsageFaultStatus) UndefinedInstruction() bool {
|
||||
return fs&nxp.SystemControl_CFSR_UNDEFINSTR != 0
|
||||
return fs&arm.SCB_CFSR_UNDEFINSTR != 0
|
||||
}
|
||||
|
||||
// IllegalUseOfEPSR: the processor has attempted to execute an instruction that
|
||||
@@ -233,19 +256,23 @@ func (fs UsageFaultStatus) UndefinedInstruction() bool {
|
||||
// points to the instruction that attempted the illegal use of the EPSR.
|
||||
//
|
||||
// This bit is not set to 1 if an undefined instruction uses the EPSR."
|
||||
func (fs UsageFaultStatus) IllegalUseOfEPSR() bool { return fs&nxp.SystemControl_CFSR_INVSTATE != 0 }
|
||||
func (fs UsageFaultStatus) IllegalUseOfEPSR() bool {
|
||||
return fs&arm.SCB_CFSR_INVSTATE != 0
|
||||
}
|
||||
|
||||
// IllegalExceptionReturn: the processor has attempted an illegal load of
|
||||
// EXC_RETURN to the PC
|
||||
//
|
||||
// "When this bit is set to 1, the PC value stacked for the exception return
|
||||
// points to the instruction that tried to perform the illegal load of the PC."
|
||||
func (fs UsageFaultStatus) IllegalExceptionReturn() bool { return fs&nxp.SystemControl_CFSR_INVPC != 0 }
|
||||
func (fs UsageFaultStatus) IllegalExceptionReturn() bool {
|
||||
return fs&arm.SCB_CFSR_INVPC != 0
|
||||
}
|
||||
|
||||
// AttemptedToAccessCoprocessor: the processor has attempted to access a
|
||||
// coprocessor
|
||||
func (fs UsageFaultStatus) AttemptedToAccessCoprocessor() bool {
|
||||
return fs&nxp.SystemControl_CFSR_NOCP != 0
|
||||
return fs&arm.SCB_CFSR_NOCP != 0
|
||||
}
|
||||
|
||||
// UnalignedMemoryAccess: the processor has made an unaligned memory access
|
||||
@@ -256,7 +283,7 @@ func (fs UsageFaultStatus) AttemptedToAccessCoprocessor() bool {
|
||||
// Unaligned LDM, STM, LDRD, and STRD instructions always fault irrespective of
|
||||
// the setting of UNALIGN_TRP."
|
||||
func (fs UsageFaultStatus) UnalignedMemoryAccess() bool {
|
||||
return fs&nxp.SystemControl_CFSR_UNALIGNED != 0
|
||||
return fs&arm.SCB_CFSR_UNALIGNED != 0
|
||||
}
|
||||
|
||||
// DivideByZero: the processor has executed an SDIV or UDIV instruction with a
|
||||
@@ -267,7 +294,9 @@ func (fs UsageFaultStatus) UnalignedMemoryAccess() bool {
|
||||
//
|
||||
// Enable trapping of divide by zero by setting the DIV_0_TRP bit in the CCR to
|
||||
// 1."
|
||||
func (fs UsageFaultStatus) DivideByZero() bool { return fs&nxp.SystemControl_CFSR_DIVBYZERO != 0 }
|
||||
func (fs UsageFaultStatus) DivideByZero() bool {
|
||||
return fs&arm.SCB_CFSR_DIVBYZERO != 0
|
||||
}
|
||||
|
||||
// Address returns the MemManage Fault Address Register if the fault status
|
||||
// indicates the address is valid.
|
||||
@@ -277,10 +306,10 @@ func (fs UsageFaultStatus) DivideByZero() bool { return fs&nxp.SystemControl_CFS
|
||||
// problems on return to a stacked active MemManage fault handler whose MMAR
|
||||
// value has been overwritten."
|
||||
func (fs MemFaultStatus) Address() (uintptr, bool) {
|
||||
if fs&nxp.SystemControl_CFSR_MMARVALID == 0 {
|
||||
if fs&arm.SCB_CFSR_MMARVALID == 0 {
|
||||
return 0, false
|
||||
} else {
|
||||
return uintptr(nxp.SystemControl.MMFAR.Get()), true
|
||||
return uintptr(arm.SCB.MMFAR.Get()), true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -296,9 +325,9 @@ func (fs MemFaultStatus) Address() (uintptr, bool) {
|
||||
// returning to a stacked active BusFault handler whose BFAR value has been
|
||||
// overwritten.""
|
||||
func (fs BusFaultStatus) Address() (uintptr, bool) {
|
||||
if fs&nxp.SystemControl_CFSR_BFARVALID == 0 {
|
||||
if fs&arm.SCB_CFSR_BFARVALID == 0 {
|
||||
return 0, false
|
||||
} else {
|
||||
return uintptr(nxp.SystemControl.BFAR.Get()), true
|
||||
return uintptr(arm.SCB.BFAR.Get()), true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@ func postinit() {}
|
||||
func main() {
|
||||
preinit()
|
||||
run()
|
||||
|
||||
// Signal successful exit.
|
||||
arm.SemihostingCall(arm.SemihostingReportException, arm.SemihostingApplicationExit)
|
||||
abort()
|
||||
}
|
||||
@@ -54,3 +56,13 @@ func putchar(c byte) {
|
||||
func waitForEvents() {
|
||||
arm.Asm("wfe")
|
||||
}
|
||||
|
||||
func abort() {
|
||||
// Signal an abnormal exit.
|
||||
arm.SemihostingCall(arm.SemihostingReportException, arm.SemihostingRunTimeErrorUnknown)
|
||||
|
||||
// Lock up forever (should be unreachable).
|
||||
for {
|
||||
arm.Asm("wfi")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
// +build mimxrt1062
|
||||
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"device/arm"
|
||||
"device/nxp"
|
||||
"machine"
|
||||
"math/bits"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const asyncScheduler = false
|
||||
|
||||
//go:extern _svectors
|
||||
var _svectors [0]byte
|
||||
|
||||
//go:extern _flexram_cfg
|
||||
var _flexram_cfg [0]byte
|
||||
|
||||
func postinit() {}
|
||||
|
||||
//export Reset_Handler
|
||||
func main() {
|
||||
|
||||
// disable interrupts
|
||||
irq := arm.DisableInterrupts()
|
||||
|
||||
// initialize FPU and VTOR, reset watchdogs
|
||||
initSystem()
|
||||
|
||||
// configure core and peripheral clocks/PLLs/PFDs
|
||||
initClocks()
|
||||
|
||||
// copy data/bss sections from flash to RAM
|
||||
preinit()
|
||||
|
||||
// initialize cache and MPU
|
||||
initCache()
|
||||
|
||||
// enable SysTick, GPIO, and peripherals
|
||||
initPeripherals()
|
||||
|
||||
// reenable interrupts
|
||||
arm.EnableInterrupts(irq)
|
||||
|
||||
run()
|
||||
abort()
|
||||
}
|
||||
|
||||
func getRamSizeConfig(itcmKB, dtcmKB uint32) uint32 {
|
||||
const minKB, disabled = uint32(4), uint32(0)
|
||||
if itcmKB < minKB {
|
||||
itcmKB = disabled
|
||||
}
|
||||
if dtcmKB < minKB {
|
||||
dtcmKB = disabled
|
||||
}
|
||||
itcmKB = uint32(bits.Len(uint(itcmKB))) << nxp.IOMUXC_GPR_GPR14_CM7_CFGITCMSZ_Pos
|
||||
dtcmKB = uint32(bits.Len(uint(dtcmKB))) << nxp.IOMUXC_GPR_GPR14_CM7_CFGDTCMSZ_Pos
|
||||
return (itcmKB & nxp.IOMUXC_GPR_GPR14_CM7_CFGITCMSZ_Msk) |
|
||||
(dtcmKB & nxp.IOMUXC_GPR_GPR14_CM7_CFGDTCMSZ_Msk)
|
||||
}
|
||||
|
||||
func initSystem() {
|
||||
|
||||
// configure SRAM capacity (512K for both ITCM and DTCM)
|
||||
ramc := uintptr(unsafe.Pointer(&_flexram_cfg))
|
||||
nxp.IOMUXC_GPR.GPR17.Set(uint32(ramc))
|
||||
nxp.IOMUXC_GPR.GPR16.Set(0x00200007)
|
||||
nxp.IOMUXC_GPR.GPR14.Set(getRamSizeConfig(512, 512))
|
||||
|
||||
// from Teensyduino
|
||||
nxp.PMU.MISC0_SET.Set(nxp.PMU_MISC0_REFTOP_SELFBIASOFF)
|
||||
|
||||
// install vector table (TODO: initialize interrupt/exception table?)
|
||||
vtor := uintptr(unsafe.Pointer(&_svectors))
|
||||
nxp.SystemControl.VTOR.Set(uint32(vtor))
|
||||
|
||||
const wdogUpdateKey = 0xD928C520
|
||||
|
||||
// disable watchdog powerdown counter
|
||||
nxp.WDOG1.WMCR.ClearBits(nxp.WDOG_WMCR_PDE_Msk)
|
||||
nxp.WDOG2.WMCR.ClearBits(nxp.WDOG_WMCR_PDE_Msk)
|
||||
|
||||
// disable watchdog
|
||||
if nxp.WDOG1.WCR.HasBits(nxp.WDOG_WCR_WDE_Msk) {
|
||||
nxp.WDOG1.WCR.ClearBits(nxp.WDOG_WCR_WDE_Msk)
|
||||
}
|
||||
if nxp.WDOG2.WCR.HasBits(nxp.WDOG_WCR_WDE_Msk) {
|
||||
nxp.WDOG2.WCR.ClearBits(nxp.WDOG_WCR_WDE_Msk)
|
||||
}
|
||||
if nxp.RTWDOG.CS.HasBits(nxp.RTWDOG_CS_CMD32EN_Msk) {
|
||||
nxp.RTWDOG.CNT.Set(wdogUpdateKey)
|
||||
} else {
|
||||
nxp.RTWDOG.CNT.Set((wdogUpdateKey >> 0) & 0xFFFF)
|
||||
nxp.RTWDOG.CNT.Set((wdogUpdateKey >> 16) & 0xFFFF)
|
||||
}
|
||||
nxp.RTWDOG.TOVAL.Set(0xFFFF)
|
||||
nxp.RTWDOG.CS.Set((nxp.RTWDOG.CS.Get() & ^uint32(nxp.RTWDOG_CS_EN_Msk)) | nxp.RTWDOG_CS_UPDATE_Msk)
|
||||
}
|
||||
|
||||
func initPeripherals() {
|
||||
|
||||
// enable FPU - set CP10, CP11 full access
|
||||
nxp.SystemControl.CPACR.SetBits(
|
||||
((nxp.SCB_CPACR_CP10_CP10_3 << nxp.SCB_CPACR_CP10_Pos) & nxp.SCB_CPACR_CP10_Msk) |
|
||||
((nxp.SCB_CPACR_CP11_CP11_3 << nxp.SCB_CPACR_CP11_Pos) & nxp.SCB_CPACR_CP11_Msk))
|
||||
|
||||
enableTimerClocks() // activate GPT/PIT clock gates
|
||||
initSysTick() // enable SysTick
|
||||
initRTC() // enable real-time clock
|
||||
|
||||
enablePinClocks() // activate IOMUXC(_GPR)/GPIO clock gates
|
||||
initPins() // configure GPIO
|
||||
|
||||
enablePeripheralClocks() // activate peripheral clock gates
|
||||
initUART() // configure UART (initialized first for debugging)
|
||||
}
|
||||
|
||||
func initPins() {
|
||||
// use fast GPIO for all pins (GPIO6-9)
|
||||
nxp.IOMUXC_GPR.GPR26.Set(0xFFFFFFFF)
|
||||
nxp.IOMUXC_GPR.GPR27.Set(0xFFFFFFFF)
|
||||
nxp.IOMUXC_GPR.GPR28.Set(0xFFFFFFFF)
|
||||
nxp.IOMUXC_GPR.GPR29.Set(0xFFFFFFFF)
|
||||
}
|
||||
|
||||
func initUART() {
|
||||
machine.UART1.Configure(machine.UARTConfig{})
|
||||
}
|
||||
|
||||
func putchar(c byte) {
|
||||
machine.UART1.WriteByte(c)
|
||||
}
|
||||
|
||||
func abort() {
|
||||
for {
|
||||
arm.Asm("wfe")
|
||||
}
|
||||
}
|
||||
|
||||
func waitForEvents() {
|
||||
arm.Asm("wfe")
|
||||
}
|
||||
@@ -0,0 +1,330 @@
|
||||
// +build mimxrt1062
|
||||
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"device/nxp"
|
||||
)
|
||||
|
||||
// Core clock frequencies (Hz)
|
||||
const (
|
||||
CORE_FREQ = 600000000 // 600 MHz
|
||||
OSC_FREQ = 24000000 // 24 MHz
|
||||
)
|
||||
|
||||
// Note from Teensyduino (cores/teensy4/startup.c):
|
||||
//
|
||||
// | ARM SysTick is used for most Ardiuno timing functions, delay(), millis(),
|
||||
// | micros(). SysTick can run from either the ARM core clock, or from an
|
||||
// | "external" clock. NXP documents it as "24 MHz XTALOSC can be the external
|
||||
// | clock source of SYSTICK" (RT1052 ref manual, rev 1, page 411). However,
|
||||
// | NXP actually hid an undocumented divide-by-240 circuit in the hardware, so
|
||||
// | the external clock is really 100 kHz. We use this clock rather than the
|
||||
// | ARM clock, to allow SysTick to maintain correct timing even when we change
|
||||
// | the ARM clock to run at different speeds.
|
||||
const SYSTICK_FREQ = 100000 // 100 kHz
|
||||
|
||||
var (
|
||||
ArmPllConfig = nxp.ClockConfigArmPll{
|
||||
LoopDivider: 100, // PLL loop divider, Fout=Fin*50
|
||||
Src: 0, // bypass clock source, 0=OSC24M, 1=CLK1_P & CLK1_N
|
||||
}
|
||||
SysPllConfig = nxp.ClockConfigSysPll{
|
||||
LoopDivider: 1, // PLL loop divider, Fout=Fin*(20+LOOP*2+NUMER/DENOM)
|
||||
Numerator: 0, // 30-bit NUMER of fractional loop divider
|
||||
Denominator: 1, // 30-bit DENOM of fractional loop divider
|
||||
Src: 0, // bypass clock source, 0=OSC24M, 1=CLK1_P & CLK1_N
|
||||
}
|
||||
Usb1PllConfig = nxp.ClockConfigUsbPll{
|
||||
Instance: 1, // USB PLL instance
|
||||
LoopDivider: 0, // PLL loop divider, Fout=Fin*20
|
||||
Src: 0, // bypass clock source, 0=OSC24M, 1=CLK1_P & CLK1_N
|
||||
}
|
||||
Usb2PllConfig = nxp.ClockConfigUsbPll{
|
||||
Instance: 2, // USB PLL instance
|
||||
LoopDivider: 0, // PLL loop divider, Fout=Fin*20
|
||||
Src: 0, // bypass clock source, 0=OSC24M, 1=CLK1_P & CLK1_N
|
||||
}
|
||||
)
|
||||
|
||||
// initClocks configures the core, buses, and all peripherals' clock source mux
|
||||
// and dividers for runtime. The clock gates for individual peripherals are all
|
||||
// disabled prior to configuration and must be enabled afterwards using one of
|
||||
// these `enable*Clocks()` functions or the respective peripheral clocks'
|
||||
// `Enable()` method from the "device/nxp" package.
|
||||
func initClocks() {
|
||||
// disable low-power mode so that __WFI doesn't lock up at runtime.
|
||||
// see: Using the MIMXRT1060/4-EVK with MCUXpresso IDE v10.3.x (v1.0.2,
|
||||
// 2019MAR01), chapter 14
|
||||
nxp.ClockModeRun.Set()
|
||||
|
||||
// enable and use 1MHz clock output
|
||||
nxp.XTALOSC24M.OSC_CONFIG2.SetBits(nxp.XTALOSC24M_OSC_CONFIG2_ENABLE_1M_Msk)
|
||||
nxp.XTALOSC24M.OSC_CONFIG2.ClearBits(nxp.XTALOSC24M_OSC_CONFIG2_MUX_1M_Msk)
|
||||
|
||||
// initialize external 24 MHz clock
|
||||
nxp.CCM_ANALOG.MISC0_CLR.Set(nxp.CCM_ANALOG_MISC0_XTAL_24M_PWD_Msk) // power
|
||||
for !nxp.XTALOSC24M.LOWPWR_CTRL.HasBits(nxp.XTALOSC24M_LOWPWR_CTRL_XTALOSC_PWRUP_STAT_Msk) {
|
||||
}
|
||||
nxp.CCM_ANALOG.MISC0_SET.Set(nxp.CCM_ANALOG_MISC0_OSC_XTALOK_EN_Msk) // detect freq
|
||||
for !nxp.CCM_ANALOG.MISC0.HasBits(nxp.CCM_ANALOG_MISC0_OSC_XTALOK_Msk) {
|
||||
}
|
||||
nxp.CCM_ANALOG.MISC0_CLR.Set(nxp.CCM_ANALOG_MISC0_OSC_XTALOK_EN_Msk)
|
||||
|
||||
// initialize internal RC OSC 24 MHz, and switch clock source to external OSC
|
||||
nxp.XTALOSC24M.LOWPWR_CTRL.SetBits(nxp.XTALOSC24M_LOWPWR_CTRL_RC_OSC_EN_Msk)
|
||||
nxp.XTALOSC24M.LOWPWR_CTRL_CLR.Set(nxp.XTALOSC24M_LOWPWR_CTRL_CLR_OSC_SEL_Msk)
|
||||
|
||||
// set oscillator ready counter value
|
||||
nxp.CCM.CCR.Set((nxp.CCM.CCR.Get() & ^uint32(nxp.CCM_CCR_OSCNT_Msk)) |
|
||||
((127 << nxp.CCM_CCR_OSCNT_Pos) & nxp.CCM_CCR_OSCNT_Msk))
|
||||
|
||||
// set PERIPH2_CLK and PERIPH to provide stable clock before PLLs initialed
|
||||
nxp.MuxIpPeriphClk2.Mux(1) // PERIPH_CLK2 select OSC24M
|
||||
nxp.MuxIpPeriph.Mux(1) // PERIPH select PERIPH_CLK2
|
||||
|
||||
// set VDD_SOC to 1.275V, necessary to config AHB to 600 MHz
|
||||
nxp.DCDC.REG3.Set((nxp.DCDC.REG3.Get() & ^uint32(nxp.DCDC_REG3_TRG_Msk)) |
|
||||
((13 << nxp.DCDC_REG3_TRG_Pos) & nxp.DCDC_REG3_TRG_Msk))
|
||||
|
||||
// wait until DCDC_STS_DC_OK bit is asserted
|
||||
for !nxp.DCDC.REG0.HasBits(nxp.DCDC_REG0_STS_DC_OK_Msk) {
|
||||
}
|
||||
|
||||
nxp.DivIpAhb.Div(0) // divide AHB_PODF (DIV1)
|
||||
|
||||
nxp.ClockIpAdc1.Enable(false) // disable ADC
|
||||
nxp.ClockIpAdc2.Enable(false) //
|
||||
|
||||
nxp.ClockIpXbar1.Enable(false) // disable XBAR
|
||||
nxp.ClockIpXbar2.Enable(false) //
|
||||
nxp.ClockIpXbar3.Enable(false) //
|
||||
|
||||
nxp.DivIpIpg.Div(3) // divide IPG_PODF (DIV4)
|
||||
nxp.DivIpArm.Div(1) // divide ARM_PODF (DIV2)
|
||||
nxp.DivIpPeriphClk2.Div(0) // divide PERIPH_CLK2_PODF (DIV1)
|
||||
|
||||
nxp.ClockIpGpt1.Enable(false) // disable GPT/PIT
|
||||
nxp.ClockIpGpt1S.Enable(false) //
|
||||
nxp.ClockIpGpt2.Enable(false) //
|
||||
nxp.ClockIpGpt2S.Enable(false) //
|
||||
nxp.ClockIpPit.Enable(false) //
|
||||
|
||||
nxp.DivIpPerclk.Div(0) // divide PERCLK_PODF (DIV1)
|
||||
|
||||
nxp.ClockIpUsdhc1.Enable(false) // disable USDHC1
|
||||
nxp.DivIpUsdhc1.Div(1) // divide USDHC1_PODF (DIV2)
|
||||
nxp.MuxIpUsdhc1.Mux(1) // USDHC1 select PLL2_PFD0
|
||||
nxp.ClockIpUsdhc2.Enable(false) // disable USDHC2
|
||||
nxp.DivIpUsdhc2.Div(1) // divide USDHC2_PODF (DIV2)
|
||||
nxp.MuxIpUsdhc2.Mux(1) // USDHC2 select PLL2_PFD0
|
||||
|
||||
nxp.ClockIpSemc.Enable(false) // disable SEMC
|
||||
nxp.DivIpSemc.Div(1) // divide SEMC_PODF (DIV2)
|
||||
nxp.MuxIpSemcAlt.Mux(0) // SEMC_ALT select PLL2_PFD2
|
||||
nxp.MuxIpSemc.Mux(1) // SEMC select SEMC_ALT
|
||||
|
||||
if false {
|
||||
// TODO: external flash is on this bus, configured via DCD block
|
||||
nxp.ClockIpFlexSpi.Enable(false) // disable FLEXSPI
|
||||
nxp.DivIpFlexSpi.Div(0) // divide FLEXSPI_PODF (DIV1)
|
||||
nxp.MuxIpFlexSpi.Mux(2) // FLEXSPI select PLL2_PFD2
|
||||
}
|
||||
nxp.ClockIpFlexSpi2.Enable(false) // disable FLEXSPI2
|
||||
nxp.DivIpFlexSpi2.Div(0) // divide FLEXSPI2_PODF (DIV1)
|
||||
nxp.MuxIpFlexSpi2.Mux(0) // FLEXSPI2 select PLL2_PFD2
|
||||
|
||||
nxp.ClockIpCsi.Enable(false) // disable CSI
|
||||
nxp.DivIpCsi.Div(1) // divide CSI_PODF (DIV2)
|
||||
nxp.MuxIpCsi.Mux(0) // CSI select OSC24M
|
||||
|
||||
nxp.ClockIpLpspi1.Enable(false) // disable LPSPI
|
||||
nxp.ClockIpLpspi2.Enable(false) //
|
||||
nxp.ClockIpLpspi3.Enable(false) //
|
||||
nxp.ClockIpLpspi4.Enable(false) //
|
||||
nxp.DivIpLpspi.Div(3) // divide LPSPI_PODF (DIV4)
|
||||
nxp.MuxIpLpspi.Mux(2) // LPSPI select PLL2
|
||||
|
||||
nxp.ClockIpTrace.Enable(false) // disable TRACE
|
||||
nxp.DivIpTrace.Div(3) // divide TRACE_PODF (DIV4)
|
||||
nxp.MuxIpTrace.Mux(0) // TRACE select PLL2_MAIN
|
||||
|
||||
nxp.ClockIpSai1.Enable(false) // disable SAI1
|
||||
nxp.DivIpSai1Pre.Div(3) // divide SAI1_CLK_PRED (DIV4)
|
||||
nxp.DivIpSai1.Div(1) // divide SAI1_CLK_PODF (DIV2)
|
||||
nxp.MuxIpSai1.Mux(0) // SAI1 select PLL3_PFD2
|
||||
nxp.ClockIpSai2.Enable(false) // disable SAI2
|
||||
nxp.DivIpSai2Pre.Div(3) // divide SAI2_CLK_PRED (DIV4)
|
||||
nxp.DivIpSai2.Div(1) // divide SAI2_CLK_PODF (DIV2)
|
||||
nxp.MuxIpSai2.Mux(0) // SAI2 select PLL3_PFD2
|
||||
nxp.ClockIpSai3.Enable(false) // disable SAI3
|
||||
nxp.DivIpSai3Pre.Div(3) // divide SAI3_CLK_PRED (DIV4)
|
||||
nxp.DivIpSai3.Div(1) // divide SAI3_CLK_PODF (DIV2)
|
||||
nxp.MuxIpSai3.Mux(0) // SAI3 select PLL3_PFD2
|
||||
|
||||
nxp.ClockIpLpi2c1.Enable(false) // disable LPI2C
|
||||
nxp.ClockIpLpi2c2.Enable(false) //
|
||||
nxp.ClockIpLpi2c3.Enable(false) //
|
||||
nxp.DivIpLpi2c.Div(0) // divide LPI2C_CLK_PODF (DIV1)
|
||||
nxp.MuxIpLpi2c.Mux(0) // LPI2C select PLL3_SW_60M
|
||||
|
||||
nxp.ClockIpCan1.Enable(false) // disable CAN
|
||||
nxp.ClockIpCan2.Enable(false) //
|
||||
nxp.ClockIpCan3.Enable(false) //
|
||||
nxp.ClockIpCan1S.Enable(false) //
|
||||
nxp.ClockIpCan2S.Enable(false) //
|
||||
nxp.ClockIpCan3S.Enable(false) //
|
||||
nxp.DivIpCan.Div(1) // divide CAN_CLK_PODF (DIV2)
|
||||
nxp.MuxIpCan.Mux(2) // CAN select PLL3_SW_80M
|
||||
|
||||
nxp.ClockIpLpuart1.Enable(false) // disable UART
|
||||
nxp.ClockIpLpuart2.Enable(false) //
|
||||
nxp.ClockIpLpuart3.Enable(false) //
|
||||
nxp.ClockIpLpuart4.Enable(false) //
|
||||
nxp.ClockIpLpuart5.Enable(false) //
|
||||
nxp.ClockIpLpuart6.Enable(false) //
|
||||
nxp.ClockIpLpuart7.Enable(false) //
|
||||
nxp.ClockIpLpuart8.Enable(false) //
|
||||
nxp.DivIpUart.Div(0) // divide UART_CLK_PODF (DIV1)
|
||||
nxp.MuxIpUart.Mux(1) // UART select OSC
|
||||
|
||||
nxp.ClockIpLcdPixel.Enable(false) // disable LCDIF
|
||||
nxp.DivIpLcdifPre.Div(1) // divide LCDIF_PRED (DIV2)
|
||||
nxp.DivIpLcdif.Div(3) // divide LCDIF_CLK_PODF (DIV4)
|
||||
nxp.MuxIpLcdifPre.Mux(5) // LCDIF_PRE select PLL3_PFD1
|
||||
|
||||
nxp.ClockIpSpdif.Enable(false) // disable SPDIF
|
||||
nxp.DivIpSpdif0Pre.Div(1) // divide SPDIF0_CLK_PRED (DIV2)
|
||||
nxp.DivIpSpdif0.Div(7) // divide SPDIF0_CLK_PODF (DIV8)
|
||||
nxp.MuxIpSpdif.Mux(3) // SPDIF select PLL3_SW
|
||||
|
||||
nxp.ClockIpFlexio1.Enable(false) // disable FLEXIO1
|
||||
nxp.DivIpFlexio1Pre.Div(1) // divide FLEXIO1_CLK_PRED (DIV2)
|
||||
nxp.DivIpFlexio1.Div(7) // divide FLEXIO1_CLK_PODF (DIV8)
|
||||
nxp.MuxIpFlexio1.Mux(3) // FLEXIO1 select PLL3_SW
|
||||
nxp.ClockIpFlexio2.Enable(false) // disable FLEXIO2
|
||||
nxp.DivIpFlexio2Pre.Div(1) // divide FLEXIO2_CLK_PRED (DIV2)
|
||||
nxp.DivIpFlexio2.Div(7) // divide FLEXIO2_CLK_PODF (DIV8)
|
||||
nxp.MuxIpFlexio2.Mux(3) // FLEXIO2 select PLL3_SW
|
||||
|
||||
nxp.MuxIpPll3Sw.Mux(0) // PLL3_SW select PLL3_MAIN
|
||||
|
||||
ArmPllConfig.Configure() // init ARM PLL
|
||||
// SYS PLL (PLL2) @ 528 MHz
|
||||
// PFD0 = 396 MHz -> USDHC1/USDHC2(DIV2)=198 MHz
|
||||
// PFD1 = 594 MHz -> (currently unused)
|
||||
// PFD2 = 327.72 MHz -> SEMC(DIV2)=163.86 MHz, FlexSPI/FlexSPI2=327.72 MHz
|
||||
// PFD3 = 454.73 MHz -> (currently unused)
|
||||
SysPllConfig.Configure(24, 16, 29, 16) // init SYS PLL and PFDs
|
||||
|
||||
// USB1 PLL (PLL3) @ 480 MHz
|
||||
// PFD0 -> (currently unused)
|
||||
// PFD1 -> (currently unused)
|
||||
// PFD2 -> (currently unused)
|
||||
// PFD3 -> (currently unused)
|
||||
Usb1PllConfig.Configure() // init USB1 PLL and PFDs
|
||||
Usb2PllConfig.Configure() // init USB2 PLL
|
||||
|
||||
nxp.MuxIpPrePeriph.Mux(3) // PRE_PERIPH select ARM_PLL
|
||||
nxp.MuxIpPeriph.Mux(0) // PERIPH select PRE_PERIPH
|
||||
nxp.MuxIpPeriphClk2.Mux(1) // PERIPH_CLK2 select OSC
|
||||
nxp.MuxIpPerclk.Mux(1) // PERCLK select OSC
|
||||
|
||||
// set LVDS1 clock source
|
||||
nxp.CCM_ANALOG.MISC1.Set((nxp.CCM_ANALOG.MISC1.Get() & ^uint32(nxp.CCM_ANALOG_MISC1_LVDS1_CLK_SEL_Msk)) |
|
||||
((0 << nxp.CCM_ANALOG_MISC1_LVDS1_CLK_SEL_Pos) & nxp.CCM_ANALOG_MISC1_LVDS1_CLK_SEL_Msk))
|
||||
|
||||
// set CLOCK_OUT1 divider
|
||||
nxp.CCM.CCOSR.Set((nxp.CCM.CCOSR.Get() & ^uint32(nxp.CCM_CCOSR_CLKO1_DIV_Msk)) |
|
||||
((0 << nxp.CCM_CCOSR_CLKO1_DIV_Pos) & nxp.CCM_CCOSR_CLKO1_DIV_Msk))
|
||||
// set CLOCK_OUT1 source
|
||||
nxp.CCM.CCOSR.Set((nxp.CCM.CCOSR.Get() & ^uint32(nxp.CCM_CCOSR_CLKO1_SEL_Msk)) |
|
||||
((1 << nxp.CCM_CCOSR_CLKO1_SEL_Pos) & nxp.CCM_CCOSR_CLKO1_SEL_Msk))
|
||||
// set CLOCK_OUT2 divider
|
||||
nxp.CCM.CCOSR.Set((nxp.CCM.CCOSR.Get() & ^uint32(nxp.CCM_CCOSR_CLKO2_DIV_Msk)) |
|
||||
((0 << nxp.CCM_CCOSR_CLKO2_DIV_Pos) & nxp.CCM_CCOSR_CLKO2_DIV_Msk))
|
||||
// set CLOCK_OUT2 source
|
||||
nxp.CCM.CCOSR.Set((nxp.CCM.CCOSR.Get() & ^uint32(nxp.CCM_CCOSR_CLKO2_SEL_Msk)) |
|
||||
((18 << nxp.CCM_CCOSR_CLKO2_SEL_Pos) & nxp.CCM_CCOSR_CLKO2_SEL_Msk))
|
||||
|
||||
nxp.CCM.CCOSR.ClearBits(nxp.CCM_CCOSR_CLK_OUT_SEL_Msk) // set CLK_OUT1 drives CLK_OUT
|
||||
nxp.CCM.CCOSR.SetBits(nxp.CCM_CCOSR_CLKO1_EN_Msk) // enable CLK_OUT1
|
||||
nxp.CCM.CCOSR.SetBits(nxp.CCM_CCOSR_CLKO2_EN_Msk) // enable CLK_OUT2
|
||||
|
||||
nxp.ClockIpIomuxcGpr.Enable(false) // disable IOMUXC_GPR
|
||||
nxp.ClockIpIomuxc.Enable(false) // disable IOMUXC
|
||||
// set GPT1 High frequency reference clock source
|
||||
nxp.IOMUXC_GPR.GPR5.ClearBits(nxp.IOMUXC_GPR_GPR5_VREF_1M_CLK_GPT1_Msk)
|
||||
// set GPT2 High frequency reference clock source
|
||||
nxp.IOMUXC_GPR.GPR5.ClearBits(nxp.IOMUXC_GPR_GPR5_VREF_1M_CLK_GPT2_Msk)
|
||||
|
||||
nxp.ClockIpGpio1.Enable(false) // disable GPIO
|
||||
nxp.ClockIpGpio2.Enable(false) //
|
||||
nxp.ClockIpGpio3.Enable(false) //
|
||||
nxp.ClockIpGpio4.Enable(false) //
|
||||
}
|
||||
|
||||
func enableTimerClocks() {
|
||||
|
||||
nxp.ClockIpGpt1.Enable(true) // enable GPT/PIT
|
||||
nxp.ClockIpGpt1S.Enable(true) //
|
||||
nxp.ClockIpGpt2.Enable(true) //
|
||||
nxp.ClockIpGpt2S.Enable(true) //
|
||||
nxp.ClockIpPit.Enable(true) //
|
||||
}
|
||||
|
||||
func enablePinClocks() {
|
||||
|
||||
nxp.ClockIpIomuxcGpr.Enable(true) // enable IOMUXC
|
||||
nxp.ClockIpIomuxc.Enable(true) //
|
||||
|
||||
nxp.ClockIpGpio1.Enable(true) // enable GPIO
|
||||
nxp.ClockIpGpio2.Enable(true) //
|
||||
nxp.ClockIpGpio3.Enable(true) //
|
||||
nxp.ClockIpGpio4.Enable(true) //
|
||||
}
|
||||
|
||||
func enablePeripheralClocks() {
|
||||
|
||||
nxp.ClockIpAdc1.Enable(true) // enable ADC
|
||||
nxp.ClockIpAdc2.Enable(true) //
|
||||
|
||||
nxp.ClockIpXbar1.Enable(true) // enable XBAR
|
||||
nxp.ClockIpXbar2.Enable(true) //
|
||||
nxp.ClockIpXbar3.Enable(true) //
|
||||
|
||||
nxp.ClockIpUsdhc1.Enable(true) // enable USDHC
|
||||
nxp.ClockIpUsdhc2.Enable(true) //
|
||||
|
||||
nxp.ClockIpSemc.Enable(true) // enable SEMC
|
||||
|
||||
nxp.ClockIpFlexSpi2.Enable(true) // enable FLEXSPI2
|
||||
|
||||
nxp.ClockIpLpspi1.Enable(true) // enable LPSPI
|
||||
nxp.ClockIpLpspi2.Enable(true) //
|
||||
nxp.ClockIpLpspi3.Enable(true) //
|
||||
nxp.ClockIpLpspi4.Enable(true) //
|
||||
|
||||
nxp.ClockIpLpi2c1.Enable(true) // enable LPI2C
|
||||
nxp.ClockIpLpi2c2.Enable(true) //
|
||||
nxp.ClockIpLpi2c3.Enable(true) //
|
||||
|
||||
nxp.ClockIpCan1.Enable(true) // enable CAN
|
||||
nxp.ClockIpCan2.Enable(true) //
|
||||
nxp.ClockIpCan3.Enable(true) //
|
||||
nxp.ClockIpCan1S.Enable(true) //
|
||||
nxp.ClockIpCan2S.Enable(true) //
|
||||
nxp.ClockIpCan3S.Enable(true) //
|
||||
|
||||
nxp.ClockIpLpuart1.Enable(true) // enable UART
|
||||
nxp.ClockIpLpuart2.Enable(true) //
|
||||
nxp.ClockIpLpuart3.Enable(true) //
|
||||
nxp.ClockIpLpuart4.Enable(true) //
|
||||
nxp.ClockIpLpuart5.Enable(true) //
|
||||
nxp.ClockIpLpuart6.Enable(true) //
|
||||
nxp.ClockIpLpuart7.Enable(true) //
|
||||
nxp.ClockIpLpuart8.Enable(true) //
|
||||
|
||||
nxp.ClockIpFlexio1.Enable(true) // enable FLEXIO
|
||||
nxp.ClockIpFlexio2.Enable(true) //
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
// +build mimxrt1062
|
||||
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"device/nxp"
|
||||
)
|
||||
|
||||
func initCache() {
|
||||
|
||||
nxp.MPU.Enable(false)
|
||||
|
||||
// add Default [0] region to deny access to whole address space to workaround
|
||||
// speculative prefetch. Refer to Arm errata 1013783-B for more details.
|
||||
|
||||
// [0] Default {OVERLAY}: 4 GiB, -access, @device, -exec, -share, -cache, -buffer, -subregion
|
||||
nxp.MPU.SetRBAR(0, 0x00000000)
|
||||
nxp.MPU.SetRASR(nxp.RGNSZ_4GB, nxp.PERM_NONE, nxp.EXTN_DEVICE, false, false, false, false, false)
|
||||
|
||||
// [1] Peripherals {OVERLAY}: 64 MiB, +ACCESS, @device, +EXEC, -share, -cache, -buffer, -subregion
|
||||
nxp.MPU.SetRBAR(1, 0x40000000)
|
||||
nxp.MPU.SetRASR(nxp.RGNSZ_64MB, nxp.PERM_FULL, nxp.EXTN_DEVICE, true, false, false, false, false)
|
||||
|
||||
// [2] RAM {OVERLAY}: 1 GiB, +ACCESS, @device, +EXEC, -share, -cache, -buffer, -subregion
|
||||
nxp.MPU.SetRBAR(2, 0x00000000)
|
||||
nxp.MPU.SetRASR(nxp.RGNSZ_1GB, nxp.PERM_FULL, nxp.EXTN_DEVICE, true, false, false, false, false)
|
||||
|
||||
// [3] ITCM: 512 KiB, +ACCESS, #NORMAL, +EXEC, -share, -cache, -buffer, -subregion
|
||||
nxp.MPU.SetRBAR(3, 0x00000000)
|
||||
nxp.MPU.SetRASR(nxp.RGNSZ_512KB, nxp.PERM_FULL, nxp.EXTN_NORMAL, true, false, false, false, false)
|
||||
|
||||
// [4] DTCM: 512 KiB, +ACCESS, #NORMAL, +EXEC, -share, -cache, -buffer, -subregion
|
||||
nxp.MPU.SetRBAR(4, 0x20000000)
|
||||
nxp.MPU.SetRASR(nxp.RGNSZ_512KB, nxp.PERM_FULL, nxp.EXTN_NORMAL, true, false, false, false, false)
|
||||
|
||||
// [5] RAM (AXI): 512 KiB, +ACCESS, #NORMAL, +EXEC, -share, +CACHE, +BUFFER, -subregion
|
||||
nxp.MPU.SetRBAR(5, 0x20200000)
|
||||
nxp.MPU.SetRASR(nxp.RGNSZ_512KB, nxp.PERM_FULL, nxp.EXTN_NORMAL, true, false, true, true, false)
|
||||
|
||||
// [6] FlexSPI: 512 MiB, +ACCESS, #NORMAL, +EXEC, -share, +CACHE, +BUFFER, -subregion
|
||||
nxp.MPU.SetRBAR(6, 0x70000000)
|
||||
nxp.MPU.SetRASR(nxp.RGNSZ_512MB, nxp.PERM_FULL, nxp.EXTN_NORMAL, true, false, true, true, false)
|
||||
|
||||
// [7] QSPI flash: 2 MiB, +ACCESS, #NORMAL, +EXEC, -share, +CACHE, +BUFFER, -subregion
|
||||
nxp.MPU.SetRBAR(7, 0x60000000)
|
||||
nxp.MPU.SetRASR(nxp.RGNSZ_2MB, nxp.PERM_FULL, nxp.EXTN_NORMAL, true, false, true, true, false)
|
||||
|
||||
nxp.MPU.Enable(true)
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
// +build mimxrt1062
|
||||
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"device/arm"
|
||||
"device/nxp"
|
||||
"runtime/interrupt"
|
||||
"runtime/volatile"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type timeUnit int64
|
||||
|
||||
const (
|
||||
lastCycle = SYSTICK_FREQ/1000 - 1
|
||||
cyclesPerMicro = CORE_FREQ / 1000000
|
||||
)
|
||||
|
||||
const (
|
||||
pitFreq = OSC_FREQ // PIT/GPT are muxed to 24 MHz OSC
|
||||
pitCyclesPerMicro = pitFreq / 1000000
|
||||
pitSleepTimer = 0 // x4 32-bit PIT timers [0..3]
|
||||
)
|
||||
|
||||
var (
|
||||
tickCount volatile.Register64
|
||||
cycleCount volatile.Register32
|
||||
pitActive volatile.Register32
|
||||
pitTimeout interrupt.Interrupt
|
||||
)
|
||||
|
||||
var (
|
||||
// debug exception and monitor control
|
||||
DEM_CR = (*volatile.Register32)(unsafe.Pointer(uintptr(0xe000edfc)))
|
||||
DWT_CR = (*volatile.Register32)(unsafe.Pointer(uintptr(0xe0001000)))
|
||||
DWT_CYCCNT = (*volatile.Register32)(unsafe.Pointer(uintptr(0xe0001004)))
|
||||
)
|
||||
|
||||
func ticksToNanoseconds(ticks timeUnit) int64 {
|
||||
return int64(ticks) * 1000
|
||||
}
|
||||
|
||||
func nanosecondsToTicks(ns int64) timeUnit {
|
||||
return timeUnit(ns / 1000)
|
||||
}
|
||||
|
||||
func initSysTick() {
|
||||
|
||||
const (
|
||||
traceEnable = 0x01000000 // enable debugging & monitoring blocks
|
||||
cycleCountEnable = 0x00000001 // cycle count register
|
||||
)
|
||||
|
||||
// disable SysTick if already running
|
||||
if arm.SYST.SYST_CSR.HasBits(arm.SYST_CSR_ENABLE_Msk) {
|
||||
arm.SYST.SYST_CSR.ClearBits(arm.SYST_CSR_ENABLE_Msk)
|
||||
}
|
||||
|
||||
// zeroize the counter
|
||||
tickCount.Set(0)
|
||||
arm.SYST.SYST_RVR.Set(lastCycle)
|
||||
arm.SYST.SYST_CVR.Set(0)
|
||||
arm.SYST.SYST_CSR.Set(arm.SYST_CSR_TICKINT | arm.SYST_CSR_ENABLE)
|
||||
|
||||
// set SysTick and PendSV priority to 32
|
||||
nxp.SystemControl.SHPR3.Set((0x20 << nxp.SCB_SHPR3_PRI_15_Pos) |
|
||||
(0x20 << nxp.SCB_SHPR3_PRI_14_Pos))
|
||||
|
||||
// turn on cycle counter
|
||||
DEM_CR.SetBits(traceEnable)
|
||||
DWT_CR.SetBits(cycleCountEnable)
|
||||
cycleCount.Set(DWT_CYCCNT.Get())
|
||||
|
||||
// enable PIT, disable counters
|
||||
nxp.PIT.MCR.Set(0)
|
||||
for i := range nxp.PIT.TIMER {
|
||||
nxp.PIT.TIMER[i].TCTRL.Set(0)
|
||||
}
|
||||
|
||||
// register sleep timer interrupt
|
||||
pitTimeout = interrupt.New(nxp.IRQ_PIT, timerWake)
|
||||
pitTimeout.SetPriority(0x21)
|
||||
pitTimeout.Enable()
|
||||
}
|
||||
|
||||
func initRTC() {
|
||||
if !nxp.SNVS.LPCR.HasBits(nxp.SNVS_LPCR_SRTC_ENV) {
|
||||
// if SRTC isn't running, start it with default Jan 1, 2019
|
||||
nxp.SNVS.LPSRTCLR.Set(uint32((0x5c2aad80 << 15) & 0xFFFFFFFF))
|
||||
nxp.SNVS.LPSRTCMR.Set(uint32(0x5c2aad80 >> 17))
|
||||
nxp.SNVS.LPCR.SetBits(nxp.SNVS_LPCR_SRTC_ENV)
|
||||
}
|
||||
}
|
||||
|
||||
//go:export SysTick_Handler
|
||||
func tick() {
|
||||
tickCount.Set(tickCount.Get() + 1)
|
||||
cycleCount.Set(DWT_CYCCNT.Get())
|
||||
}
|
||||
|
||||
func ticks() timeUnit {
|
||||
mask := arm.DisableInterrupts()
|
||||
tick := tickCount.Get()
|
||||
cycs := cycleCount.Get()
|
||||
curr := DWT_CYCCNT.Get()
|
||||
arm.EnableInterrupts(mask)
|
||||
var diff uint32
|
||||
if curr < cycs { // cycle counter overflow/rollover occurred
|
||||
diff = (0xFFFFFFFF - cycs) + curr
|
||||
} else {
|
||||
diff = curr - cycs
|
||||
}
|
||||
frac := uint64(diff*0xFFFFFFFF/cyclesPerMicro) >> 32
|
||||
if frac > 1000 {
|
||||
frac = 1000
|
||||
}
|
||||
return timeUnit(1000*tick + frac)
|
||||
}
|
||||
|
||||
func sleepTicks(duration timeUnit) {
|
||||
if duration >= 0 {
|
||||
curr := ticks()
|
||||
last := curr + duration // 64-bit overflow unlikely
|
||||
for curr < last {
|
||||
cycles := timeUnit((last - curr) / pitCyclesPerMicro)
|
||||
if cycles > 0xFFFFFFFF {
|
||||
cycles = 0xFFFFFFFF
|
||||
}
|
||||
if !timerSleep(uint32(cycles)) {
|
||||
return // return early due to interrupt
|
||||
}
|
||||
curr = ticks()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func timerSleep(cycles uint32) bool {
|
||||
pitActive.Set(1)
|
||||
nxp.PIT.TIMER[pitSleepTimer].LDVAL.Set(cycles)
|
||||
nxp.PIT.TIMER[pitSleepTimer].TCTRL.Set(nxp.PIT_TIMER_TCTRL_TIE) // enable interrupts
|
||||
nxp.PIT.TIMER[pitSleepTimer].TCTRL.SetBits(nxp.PIT_TIMER_TCTRL_TEN) // start timer
|
||||
for {
|
||||
//arm.Asm("wfi") // TODO: causes hardfault! why?
|
||||
if pitActive.Get() == 0 {
|
||||
return true
|
||||
}
|
||||
if hasScheduler {
|
||||
break // some other interrupt occurred and needs servicing
|
||||
}
|
||||
}
|
||||
timerWake(interrupt.Interrupt{}) // clear and disable timer
|
||||
return false
|
||||
}
|
||||
|
||||
func timerWake(interrupt.Interrupt) {
|
||||
pitActive.Set(0)
|
||||
// TFLGn[TIF] are set to 1 when a timeout occurs on the associated timer, and
|
||||
// are cleared to 0 by writing a 1 to the corresponding TFLGn[TIF].
|
||||
nxp.PIT.TIMER[pitSleepTimer].TFLG.Set(nxp.PIT_TIMER_TFLG_TIF) // clear interrupt flag
|
||||
nxp.PIT.TIMER[pitSleepTimer].TCTRL.Set(0) // disable timer/interrupt enable flags
|
||||
}
|
||||
@@ -8,22 +8,67 @@ type timeUnit int64
|
||||
|
||||
const asyncScheduler = false
|
||||
|
||||
const (
|
||||
// Handles
|
||||
infoTypeTotalMemorySize = 6 // Total amount of memory available for process.
|
||||
infoTypeUsedMemorySize = 7 // Amount of memory currently used by process.
|
||||
currentProcessHandle = 0xFFFF8001 // Pseudo handle for the current process.
|
||||
|
||||
// Types of config Entry
|
||||
envEntryTypeEndOfList = 0 // Entry list terminator.
|
||||
envEntryTypeMainThreadHandle = 1 // Provides the handle to the main thread.
|
||||
envEntryTypeOverrideHeap = 3 // Provides heap override information.
|
||||
|
||||
// Default heap size allocated by libnx
|
||||
defaultHeapSize = 0x2000000 * 16
|
||||
|
||||
debugInit = false
|
||||
)
|
||||
|
||||
//go:extern _saved_return_address
|
||||
var savedReturnAddress uintptr
|
||||
|
||||
//export __stack_top
|
||||
var stackTop uintptr
|
||||
|
||||
//go:extern _context
|
||||
var context uintptr
|
||||
|
||||
//go:extern _main_thread
|
||||
var mainThread uintptr
|
||||
|
||||
var (
|
||||
heapStart = uintptr(0)
|
||||
heapEnd = uintptr(0)
|
||||
usedRam = uint64(0)
|
||||
totalRam = uint64(0)
|
||||
totalHeap = uint64(0)
|
||||
)
|
||||
|
||||
func postinit() {}
|
||||
|
||||
func preinit() {
|
||||
// Unsafe to use heap here
|
||||
setupEnv()
|
||||
setupHeap()
|
||||
}
|
||||
|
||||
// Entry point for Go. Initialize all packages and call main.main().
|
||||
//export main
|
||||
func main() int {
|
||||
func main() {
|
||||
preinit()
|
||||
run()
|
||||
|
||||
// Call exit to correctly finish the program
|
||||
// Without this, the application crashes at start, not sure why
|
||||
return exit(0)
|
||||
for {
|
||||
exit(0)
|
||||
}
|
||||
}
|
||||
|
||||
// sleepTicks sleeps for the specified system ticks
|
||||
func sleepTicks(d timeUnit) {
|
||||
sleepThread(uint64(ticksToNanoseconds(d)))
|
||||
svcSleepThread(uint64(ticksToNanoseconds(d)))
|
||||
}
|
||||
|
||||
// armTicksToNs converts cpu ticks to nanoseconds
|
||||
@@ -46,8 +91,8 @@ var stdoutBuffer = make([]byte, 120)
|
||||
var position = 0
|
||||
|
||||
func putchar(c byte) {
|
||||
if c == '\n' || position > len(stdoutBuffer) {
|
||||
nxOutputString(&stdoutBuffer[0], uint64(position))
|
||||
if c == '\n' || position >= len(stdoutBuffer) {
|
||||
svcOutputDebugString(&stdoutBuffer[0], uint64(position))
|
||||
position = 0
|
||||
return
|
||||
}
|
||||
@@ -72,11 +117,159 @@ func write(fd int32, buf *byte, count int) int {
|
||||
return count
|
||||
}
|
||||
|
||||
//export sleepThread
|
||||
func sleepThread(nanos uint64)
|
||||
// exit checks if a savedReturnAddress were provided by the launcher
|
||||
// if so, calls the nxExit which restores the stack and returns to launcher
|
||||
// otherwise just calls systemcall exit
|
||||
func exit(code int) {
|
||||
if savedReturnAddress == 0 {
|
||||
svcExitProcess(code)
|
||||
return
|
||||
}
|
||||
|
||||
//export exit
|
||||
func exit(code int) int
|
||||
nxExit(code, stackTop, savedReturnAddress)
|
||||
}
|
||||
|
||||
type configEntry struct {
|
||||
Key uint32
|
||||
Flags uint32
|
||||
Value [2]uint64
|
||||
}
|
||||
|
||||
func setupEnv() {
|
||||
if debugInit {
|
||||
println("Saved Return Address:", savedReturnAddress)
|
||||
println("Context:", context)
|
||||
println("Main Thread Handle:", mainThread)
|
||||
}
|
||||
|
||||
// See https://switchbrew.org/w/index.php?title=Homebrew_ABI
|
||||
// Here we parse only the required configs for initializing
|
||||
if context != 0 {
|
||||
ptr := context
|
||||
entry := (*configEntry)(unsafe.Pointer(ptr))
|
||||
for entry.Key != envEntryTypeEndOfList {
|
||||
switch entry.Key {
|
||||
case envEntryTypeOverrideHeap:
|
||||
if debugInit {
|
||||
println("Got heap override")
|
||||
}
|
||||
heapStart = uintptr(entry.Value[0])
|
||||
heapEnd = heapStart + uintptr(entry.Value[1])
|
||||
case envEntryTypeMainThreadHandle:
|
||||
mainThread = uintptr(entry.Value[0])
|
||||
default:
|
||||
if entry.Flags&1 > 0 {
|
||||
// Mandatory but not parsed
|
||||
runtimePanic("mandatory config entry not parsed")
|
||||
}
|
||||
}
|
||||
ptr += unsafe.Sizeof(configEntry{})
|
||||
entry = (*configEntry)(unsafe.Pointer(ptr))
|
||||
}
|
||||
}
|
||||
// Fetch used / total RAM for allocating HEAP
|
||||
svcGetInfo(&totalRam, infoTypeTotalMemorySize, currentProcessHandle, 0)
|
||||
svcGetInfo(&usedRam, infoTypeUsedMemorySize, currentProcessHandle, 0)
|
||||
}
|
||||
|
||||
func setupHeap() {
|
||||
if heapStart != 0 {
|
||||
if debugInit {
|
||||
print("Heap already overrided by hblauncher")
|
||||
}
|
||||
// Already overrided
|
||||
return
|
||||
}
|
||||
|
||||
if debugInit {
|
||||
print("No heap override. Using normal initialization")
|
||||
}
|
||||
|
||||
size := uint32(defaultHeapSize)
|
||||
|
||||
if totalRam > usedRam+0x200000 {
|
||||
// Get maximum possible heap
|
||||
size = uint32(totalRam-usedRam-0x200000) & ^uint32(0x1FFFFF)
|
||||
}
|
||||
|
||||
if size < defaultHeapSize {
|
||||
size = defaultHeapSize
|
||||
}
|
||||
|
||||
if debugInit {
|
||||
println("Trying to allocate", size, "bytes of heap")
|
||||
}
|
||||
|
||||
svcSetHeapSize(&heapStart, uint64(size))
|
||||
|
||||
if heapStart == 0 {
|
||||
runtimePanic("failed to allocate heap")
|
||||
}
|
||||
|
||||
totalHeap = uint64(size)
|
||||
|
||||
heapEnd = heapStart + uintptr(size)
|
||||
|
||||
if debugInit {
|
||||
println("Heap Start", heapStart)
|
||||
println("Heap End ", heapEnd)
|
||||
println("Total Heap", totalHeap)
|
||||
}
|
||||
}
|
||||
|
||||
// getHeapBase returns the start address of the heap
|
||||
// this is externally linked by gonx
|
||||
func getHeapBase() uintptr {
|
||||
return heapStart
|
||||
}
|
||||
|
||||
// getHeapEnd returns the end address of the heap
|
||||
// this is externally linked by gonx
|
||||
func getHeapEnd() uintptr {
|
||||
return heapEnd
|
||||
}
|
||||
|
||||
// getContextPtr returns the hblauncher context
|
||||
// this is externally linked by gonx
|
||||
func getContextPtr() uintptr {
|
||||
return context
|
||||
}
|
||||
|
||||
// getMainThreadHandle returns the main thread handler if any
|
||||
// this is externally linked by gonx
|
||||
func getMainThreadHandle() uintptr {
|
||||
return mainThread
|
||||
}
|
||||
|
||||
//export armGetSystemTick
|
||||
func getArmSystemTick() int64
|
||||
|
||||
// nxExit exits the program to homebrew launcher
|
||||
//export __nx_exit
|
||||
func nxExit(code int, stackTop uintptr, exitFunction uintptr)
|
||||
|
||||
// Horizon System Calls
|
||||
// svcSetHeapSize Set the process heap to a given size. It can both extend and shrink the heap.
|
||||
// svc 0x01
|
||||
//export svcSetHeapSize
|
||||
func svcSetHeapSize(addr *uintptr, length uint64) uint64
|
||||
|
||||
// svcExitProcess Exits the current process.
|
||||
// svc 0x07
|
||||
//export svcExitProcess
|
||||
func svcExitProcess(code int)
|
||||
|
||||
// svcSleepThread Sleeps the current thread for the specified amount of time.
|
||||
// svc 0x0B
|
||||
//export svcSleepThread
|
||||
func svcSleepThread(nanos uint64)
|
||||
|
||||
// svcOutputDebugString Outputs debug text, if used during debugging.
|
||||
// svc 0x27
|
||||
//export svcOutputDebugString
|
||||
func svcOutputDebugString(str *uint8, size uint64) uint64
|
||||
|
||||
// svcGetInfo Retrieves information about the system, or a certain kernel object.
|
||||
// svc 0x29
|
||||
//export svcGetInfo
|
||||
func svcGetInfo(output *uint64, id0 uint32, handle uint32, id1 uint64) uint64
|
||||
|
||||
@@ -1,45 +1,40 @@
|
||||
.section .text.armGetSystemTick, "ax", %progbits
|
||||
.global armGetSystemTick
|
||||
.type armGetSystemTick, %function
|
||||
.align 2
|
||||
armGetSystemTick:
|
||||
// Macro for writing less code
|
||||
.macro FUNC name
|
||||
.section .text.\name, "ax", %progbits
|
||||
.global \name
|
||||
.type \name, %function
|
||||
.align 2
|
||||
\name:
|
||||
.endm
|
||||
|
||||
FUNC armGetSystemTick
|
||||
mrs x0, cntpct_el0
|
||||
ret
|
||||
|
||||
.section .text.nxOutputString, "ax", %progbits
|
||||
.global nxOutputString
|
||||
.type nxOutputString, %function
|
||||
.align 2
|
||||
.cfi_startproc
|
||||
nxOutputString:
|
||||
svc 0x27
|
||||
ret
|
||||
.cfi_endproc
|
||||
// Horizon System Calls
|
||||
// https://switchbrew.org/wiki/SVC
|
||||
FUNC svcSetHeapSize
|
||||
str x0, [sp, #-16]!
|
||||
svc 0x1
|
||||
ldr x2, [sp], #16
|
||||
str x1, [x2]
|
||||
ret
|
||||
|
||||
.section .text.exit, "ax", %progbits
|
||||
.global exit
|
||||
.type exit, %function
|
||||
.align 2
|
||||
exit:
|
||||
svc 0x7
|
||||
ret
|
||||
FUNC svcExitProcess
|
||||
svc 0x7
|
||||
ret
|
||||
|
||||
.section .text.setHeapSize, "ax", %progbits
|
||||
.global setHeapSize
|
||||
.type setHeapSize, %function
|
||||
.align 2
|
||||
setHeapSize:
|
||||
str x0, [sp, #-16]!
|
||||
svc 0x1
|
||||
ldr x2, [sp], #16
|
||||
str x1, [x2]
|
||||
ret
|
||||
FUNC svcSleepThread
|
||||
svc 0xB
|
||||
ret
|
||||
|
||||
FUNC svcOutputDebugString
|
||||
svc 0x27
|
||||
ret
|
||||
|
||||
.section .text.sleepThread, "ax", %progbits
|
||||
.global sleepThread
|
||||
.type sleepThread, %function
|
||||
.align 2
|
||||
sleepThread:
|
||||
svc 0xB
|
||||
ret
|
||||
FUNC svcGetInfo
|
||||
str x0, [sp, #-16]!
|
||||
svc 0x29
|
||||
ldr x2, [sp], #16
|
||||
str x1, [x2]
|
||||
ret
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
// +build nintendoswitch
|
||||
|
||||
// +build gc.conservative gc.leaking
|
||||
|
||||
package runtime
|
||||
|
||||
const heapSize = 0x2000000 * 16 // Default by libnx
|
||||
|
||||
var (
|
||||
heapStart = uintptr(0)
|
||||
heapEnd = uintptr(0)
|
||||
)
|
||||
|
||||
//export setHeapSize
|
||||
func setHeapSize(addr *uintptr, length uint64) uint64
|
||||
|
||||
func preinit() {
|
||||
setHeapSize(&heapStart, heapSize)
|
||||
|
||||
if heapStart == 0 {
|
||||
runtimePanic("failed to allocate heap")
|
||||
}
|
||||
|
||||
heapEnd = heapStart + heapSize
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
// +build nintendoswitch
|
||||
|
||||
// +build gc.none gc.extalloc
|
||||
|
||||
package runtime
|
||||
|
||||
func preinit() {}
|
||||
@@ -1,22 +0,0 @@
|
||||
// +build nintendoswitch
|
||||
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Result nxOutputString(const char *str, u64 size)
|
||||
//export nxOutputString
|
||||
func nxOutputString(str *uint8, size uint64) uint64
|
||||
|
||||
func NxOutputString(str string) uint64 {
|
||||
strData := (*_string)(unsafe.Pointer(&str))
|
||||
return nxOutputString((*uint8)(unsafe.Pointer(strData.ptr)), uint64(strData.length))
|
||||
}
|
||||
|
||||
//export malloc
|
||||
func extalloc(size uintptr) unsafe.Pointer
|
||||
|
||||
//export free
|
||||
func extfree(ptr unsafe.Pointer)
|
||||
@@ -120,7 +120,9 @@ func sleepTicks(d timeUnit) {
|
||||
for d != 0 {
|
||||
ticks() // update timestamp
|
||||
ticks := uint32(d) // current scaling only supports 100 usec to 6553 msec
|
||||
timerSleep(ticks)
|
||||
if !timerSleep(ticks) {
|
||||
return
|
||||
}
|
||||
d -= timeUnit(ticks)
|
||||
}
|
||||
}
|
||||
@@ -141,7 +143,8 @@ func ticks() timeUnit {
|
||||
}
|
||||
|
||||
// ticks are in microseconds
|
||||
func timerSleep(ticks uint32) {
|
||||
// returns false if an interrupt occured
|
||||
func timerSleep(ticks uint32) bool {
|
||||
timerWakeup.Set(0)
|
||||
|
||||
// STM32 timer update event period is calculated as follows:
|
||||
@@ -188,10 +191,19 @@ func timerSleep(ticks uint32) {
|
||||
// Enable the timer.
|
||||
stm32.TIM3.CR1.SetBits(stm32.TIM_CR1_CEN)
|
||||
|
||||
// wait till timer wakes up
|
||||
for timerWakeup.Get() == 0 {
|
||||
arm.Asm("wfi")
|
||||
wait:
|
||||
arm.Asm("wfi")
|
||||
if timerWakeup.Get() != 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
if hasScheduler {
|
||||
return false
|
||||
} else {
|
||||
// keep looping until the routine exits or is interrupted
|
||||
goto wait
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func handleTIM3(interrupt.Interrupt) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// +build darwin linux,!baremetal freebsd,!baremetal
|
||||
// +build darwin linux,!baremetal,!wasi freebsd,!baremetal
|
||||
// +build !nintendoswitch
|
||||
|
||||
package runtime
|
||||
@@ -37,6 +37,8 @@ type timespec struct {
|
||||
|
||||
const CLOCK_MONOTONIC_RAW = 4
|
||||
|
||||
var stackTop uintptr
|
||||
|
||||
func postinit() {}
|
||||
|
||||
// Entry point for Go. Initialize all packages and call main.main().
|
||||
@@ -44,12 +46,22 @@ func postinit() {}
|
||||
func main() int {
|
||||
preinit()
|
||||
|
||||
run()
|
||||
// Obtain the initial stack pointer right before calling the run() function.
|
||||
// The run function has been moved to a separate (non-inlined) function so
|
||||
// that the correct stack pointer is read.
|
||||
stackTop = getCurrentStackPointer()
|
||||
runMain()
|
||||
|
||||
// For libc compatibility.
|
||||
return 0
|
||||
}
|
||||
|
||||
// Must be a separate function to get the correct stack pointer.
|
||||
//go:noinline
|
||||
func runMain() {
|
||||
run()
|
||||
}
|
||||
|
||||
func putchar(c byte) {
|
||||
_putchar(int(c))
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// +build darwin linux,!baremetal freebsd,!baremetal
|
||||
// +build darwin linux,!baremetal,!wasi freebsd,!baremetal
|
||||
// +build !nintendoswitch
|
||||
|
||||
// +build gc.conservative gc.leaking
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// +build darwin linux,!baremetal freebsd,!baremetal
|
||||
// +build darwin linux,!baremetal,!wasi freebsd,!baremetal
|
||||
|
||||
// +build !nintendoswitch
|
||||
|
||||
|
||||
+23
-66
@@ -2,91 +2,48 @@
|
||||
|
||||
package runtime
|
||||
|
||||
import "unsafe"
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type timeUnit float64 // time in milliseconds, just like Date.now() in JavaScript
|
||||
|
||||
// Implements __wasi_ciovec_t and __wasi_iovec_t.
|
||||
type wasiIOVec struct {
|
||||
// Implements __wasi_iovec_t.
|
||||
type __wasi_iovec_t struct {
|
||||
buf unsafe.Pointer
|
||||
bufLen uint
|
||||
}
|
||||
|
||||
//go:wasm-module wasi_unstable
|
||||
//export fd_write
|
||||
func fd_write(id uint32, iovs *wasiIOVec, iovs_len uint, nwritten *uint) (errno uint)
|
||||
func fd_write(id uint32, iovs *__wasi_iovec_t, iovs_len uint, nwritten *uint) (errno uint)
|
||||
|
||||
func postinit() {}
|
||||
|
||||
//export _start
|
||||
func _start() {
|
||||
// These need to be initialized early so that the heap can be initialized.
|
||||
heapStart = uintptr(unsafe.Pointer(&heapStartSymbol))
|
||||
heapEnd = uintptr(wasm_memory_size(0) * wasmPageSize)
|
||||
|
||||
run()
|
||||
}
|
||||
const (
|
||||
putcharBufferSize = 120
|
||||
stdout = 1
|
||||
)
|
||||
|
||||
// Using global variables to avoid heap allocation.
|
||||
var (
|
||||
putcharBuf = byte(0)
|
||||
putcharIOVec = wasiIOVec{
|
||||
buf: unsafe.Pointer(&putcharBuf),
|
||||
bufLen: 1,
|
||||
putcharBuffer = [putcharBufferSize]byte{}
|
||||
putcharPosition uint = 0
|
||||
putcharIOVec = __wasi_iovec_t{
|
||||
buf: unsafe.Pointer(&putcharBuffer[0]),
|
||||
}
|
||||
putcharNWritten uint
|
||||
)
|
||||
|
||||
func putchar(c byte) {
|
||||
// write to stdout
|
||||
const stdout = 1
|
||||
var nwritten uint
|
||||
putcharBuf = c
|
||||
fd_write(stdout, &putcharIOVec, 1, &nwritten)
|
||||
putcharBuffer[putcharPosition] = c
|
||||
putcharPosition++
|
||||
|
||||
if c == '\n' || putcharPosition >= putcharBufferSize {
|
||||
putcharIOVec.bufLen = putcharPosition
|
||||
fd_write(stdout, &putcharIOVec, 1, &putcharNWritten)
|
||||
putcharPosition = 0
|
||||
}
|
||||
}
|
||||
|
||||
var handleEvent func()
|
||||
|
||||
//go:linkname setEventHandler syscall/js.setEventHandler
|
||||
func setEventHandler(fn func()) {
|
||||
handleEvent = fn
|
||||
}
|
||||
|
||||
//export resume
|
||||
func resume() {
|
||||
go func() {
|
||||
handleEvent()
|
||||
}()
|
||||
scheduler()
|
||||
}
|
||||
|
||||
//export go_scheduler
|
||||
func go_scheduler() {
|
||||
scheduler()
|
||||
}
|
||||
|
||||
const asyncScheduler = true
|
||||
|
||||
func ticksToNanoseconds(ticks timeUnit) int64 {
|
||||
// The JavaScript API works in float64 milliseconds, so convert to
|
||||
// nanoseconds first before converting to a timeUnit (which is a float64),
|
||||
// to avoid precision loss.
|
||||
return int64(ticks * 1e6)
|
||||
}
|
||||
|
||||
func nanosecondsToTicks(ns int64) timeUnit {
|
||||
// The JavaScript API works in float64 milliseconds, so convert to timeUnit
|
||||
// (which is a float64) first before dividing, to avoid precision loss.
|
||||
return timeUnit(ns) / 1e6
|
||||
}
|
||||
|
||||
// This function is called by the scheduler.
|
||||
// Schedule a call to runtime.scheduler, do not actually sleep.
|
||||
//export runtime.sleepTicks
|
||||
func sleepTicks(d timeUnit)
|
||||
|
||||
//export runtime.ticks
|
||||
func ticks() timeUnit
|
||||
|
||||
// Abort executes the wasm 'unreachable' instruction.
|
||||
func abort() {
|
||||
trap()
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
// +build wasm,!wasi
|
||||
|
||||
package runtime
|
||||
|
||||
import "unsafe"
|
||||
|
||||
type timeUnit float64 // time in milliseconds, just like Date.now() in JavaScript
|
||||
|
||||
//export _start
|
||||
func _start() {
|
||||
// These need to be initialized early so that the heap can be initialized.
|
||||
heapStart = uintptr(unsafe.Pointer(&heapStartSymbol))
|
||||
heapEnd = uintptr(wasm_memory_size(0) * wasmPageSize)
|
||||
|
||||
run()
|
||||
}
|
||||
|
||||
var handleEvent func()
|
||||
|
||||
//go:linkname setEventHandler syscall/js.setEventHandler
|
||||
func setEventHandler(fn func()) {
|
||||
handleEvent = fn
|
||||
}
|
||||
|
||||
//export resume
|
||||
func resume() {
|
||||
go func() {
|
||||
handleEvent()
|
||||
}()
|
||||
scheduler()
|
||||
}
|
||||
|
||||
//export go_scheduler
|
||||
func go_scheduler() {
|
||||
scheduler()
|
||||
}
|
||||
|
||||
const asyncScheduler = true
|
||||
|
||||
func ticksToNanoseconds(ticks timeUnit) int64 {
|
||||
// The JavaScript API works in float64 milliseconds, so convert to
|
||||
// nanoseconds first before converting to a timeUnit (which is a float64),
|
||||
// to avoid precision loss.
|
||||
return int64(ticks * 1e6)
|
||||
}
|
||||
|
||||
func nanosecondsToTicks(ns int64) timeUnit {
|
||||
// The JavaScript API works in float64 milliseconds, so convert to timeUnit
|
||||
// (which is a float64) first before dividing, to avoid precision loss.
|
||||
return timeUnit(ns) / 1e6
|
||||
}
|
||||
|
||||
// This function is called by the scheduler.
|
||||
// Schedule a call to runtime.scheduler, do not actually sleep.
|
||||
//export runtime.sleepTicks
|
||||
func sleepTicks(d timeUnit)
|
||||
|
||||
//export runtime.ticks
|
||||
func ticks() timeUnit
|
||||
@@ -0,0 +1,117 @@
|
||||
// +build wasm,wasi
|
||||
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type timeUnit int64
|
||||
|
||||
//export _start
|
||||
func _start() {
|
||||
// These need to be initialized early so that the heap can be initialized.
|
||||
heapStart = uintptr(unsafe.Pointer(&heapStartSymbol))
|
||||
heapEnd = uintptr(wasm_memory_size(0) * wasmPageSize)
|
||||
run()
|
||||
}
|
||||
|
||||
func ticksToNanoseconds(ticks timeUnit) int64 {
|
||||
return int64(ticks)
|
||||
}
|
||||
|
||||
func nanosecondsToTicks(ns int64) timeUnit {
|
||||
return timeUnit(ns)
|
||||
}
|
||||
|
||||
const (
|
||||
asyncScheduler = false
|
||||
timePrecisionNanoseconds = 1000 // TODO: how can we determine the appropriate `precision`?
|
||||
)
|
||||
|
||||
var (
|
||||
sleepTicksSubscription = __wasi_subscription_t{
|
||||
userData: 0,
|
||||
u: __wasi_subscription_u_t{
|
||||
tag: __wasi_eventtype_t_clock,
|
||||
u: __wasi_subscription_clock_t{
|
||||
userData: 0,
|
||||
id: 0,
|
||||
timeout: 0,
|
||||
precision: timePrecisionNanoseconds,
|
||||
flags: 0,
|
||||
},
|
||||
},
|
||||
}
|
||||
sleepTicksResult = __wasi_event_t{}
|
||||
sleepTicksNEvents uint32
|
||||
)
|
||||
|
||||
func sleepTicks(d timeUnit) {
|
||||
sleepTicksSubscription.u.u.timeout = int64(d)
|
||||
poll_oneoff(&sleepTicksSubscription, &sleepTicksResult, 1, &sleepTicksNEvents)
|
||||
}
|
||||
|
||||
func ticks() timeUnit {
|
||||
var nano int64
|
||||
clock_time_get(0, timePrecisionNanoseconds, &nano)
|
||||
return timeUnit(nano)
|
||||
}
|
||||
|
||||
// Implementations of wasi_unstable APIs
|
||||
|
||||
//go:wasm-module wasi_unstable
|
||||
//export clock_time_get
|
||||
func clock_time_get(clockid uint32, precision uint64, time *int64) (errno uint16)
|
||||
|
||||
//go:wasm-module wasi_unstable
|
||||
//export poll_oneoff
|
||||
func poll_oneoff(in *__wasi_subscription_t, out *__wasi_event_t, nsubscriptions uint32, nevents *uint32) (errno uint16)
|
||||
|
||||
type __wasi_eventtype_t = uint8
|
||||
|
||||
const (
|
||||
__wasi_eventtype_t_clock __wasi_eventtype_t = 0
|
||||
// TODO: __wasi_eventtype_t_fd_read __wasi_eventtype_t = 1
|
||||
// TODO: __wasi_eventtype_t_fd_write __wasi_eventtype_t = 2
|
||||
)
|
||||
|
||||
type (
|
||||
// https://github.com/wasmerio/wasmer/blob/1.0.0-alpha3/lib/wasi/src/syscalls/types.rs#L584-L588
|
||||
__wasi_subscription_t struct {
|
||||
userData uint64
|
||||
u __wasi_subscription_u_t
|
||||
}
|
||||
|
||||
__wasi_subscription_u_t struct {
|
||||
tag __wasi_eventtype_t
|
||||
|
||||
// TODO: support fd_read/fd_write event
|
||||
u __wasi_subscription_clock_t
|
||||
}
|
||||
|
||||
// https://github.com/wasmerio/wasmer/blob/1.0.0-alpha3/lib/wasi/src/syscalls/types.rs#L711-L718
|
||||
__wasi_subscription_clock_t struct {
|
||||
userData uint64
|
||||
id uint32
|
||||
timeout int64
|
||||
precision int64
|
||||
flags uint16
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
// https://github.com/wasmerio/wasmer/blob/1.0.0-alpha3/lib/wasi/src/syscalls/types.rs#L191-L198
|
||||
__wasi_event_t struct {
|
||||
userData uint64
|
||||
errno uint16
|
||||
eventType __wasi_eventtype_t
|
||||
|
||||
// only used for fd_read or fd_write events
|
||||
// TODO: support fd_read/fd_write event
|
||||
_ struct {
|
||||
nBytes uint64
|
||||
flags uint16
|
||||
}
|
||||
}
|
||||
)
|
||||
@@ -187,56 +187,3 @@ tinygo_switchToScheduler:
|
||||
|
||||
// Return into the scheduler, as if tinygo_switchToTask was a regular call.
|
||||
ret
|
||||
|
||||
.section .text.tinygo_scanCurrentStack
|
||||
.global tinygo_scanCurrentStack
|
||||
.type tinygo_scanCurrentStack, %function
|
||||
tinygo_scanCurrentStack:
|
||||
// Save callee-saved registers.
|
||||
push r29 // Y
|
||||
push r28 // Y
|
||||
push r17
|
||||
push r16
|
||||
push r15
|
||||
push r14
|
||||
push r13
|
||||
push r12
|
||||
push r11
|
||||
push r10
|
||||
push r9
|
||||
push r8
|
||||
push r7
|
||||
push r6
|
||||
push r5
|
||||
push r4
|
||||
push r3
|
||||
push r2
|
||||
|
||||
// Scan the stack.
|
||||
in r24, 0x3d; SPL
|
||||
in r25, 0x3e; SPH
|
||||
#if __AVR_ARCH__ == 2 || __AVR_ARCH__ == 25
|
||||
rcall tinygo_scanstack
|
||||
#else
|
||||
call tinygo_scanstack
|
||||
#endif
|
||||
|
||||
// Restore callee-saved registers.
|
||||
pop r2
|
||||
pop r3
|
||||
pop r4
|
||||
pop r5
|
||||
pop r6
|
||||
pop r7
|
||||
pop r8
|
||||
pop r9
|
||||
pop r10
|
||||
pop r11
|
||||
pop r12
|
||||
pop r13
|
||||
pop r14
|
||||
pop r15
|
||||
pop r16
|
||||
pop r17
|
||||
pop r28 // Y
|
||||
pop r29 // Y
|
||||
|
||||
@@ -136,34 +136,3 @@ tinygo_swapTask:
|
||||
#endif
|
||||
.cfi_endproc
|
||||
.size tinygo_swapTask, .-tinygo_swapTask
|
||||
|
||||
.section .text.tinygo_scanCurrentStack
|
||||
.global tinygo_scanCurrentStack
|
||||
.type tinygo_scanCurrentStack, %function
|
||||
tinygo_scanCurrentStack:
|
||||
.cfi_startproc
|
||||
// Save callee-saved registers onto the stack.
|
||||
#if defined(__thumb2__)
|
||||
push {r4-r11, lr}
|
||||
.cfi_def_cfa_offset 9*4
|
||||
#else
|
||||
mov r0, r8
|
||||
mov r1, r9
|
||||
mov r2, r10
|
||||
mov r3, r11
|
||||
push {r0-r3, lr}
|
||||
.cfi_def_cfa_offset 5*4
|
||||
push {r4-r7}
|
||||
.cfi_def_cfa_offset 4*4
|
||||
#endif
|
||||
|
||||
// Scan the stack.
|
||||
mov r0, sp
|
||||
bl tinygo_scanstack
|
||||
|
||||
// Restore stack state and return.
|
||||
add sp, #32
|
||||
.cfi_def_cfa_offset 1*4
|
||||
pop {pc}
|
||||
.cfi_endproc
|
||||
.size tinygo_scanCurrentStack, .-tinygo_scanCurrentStack
|
||||
|
||||
+34
-8
@@ -186,21 +186,47 @@ func decodeUTF8(s string, index uintptr) (rune, uintptr) {
|
||||
case x&0x80 == 0x00: // 0xxxxxxx
|
||||
return rune(x), 1
|
||||
case x&0xe0 == 0xc0: // 110xxxxx
|
||||
if remaining < 2 {
|
||||
if remaining < 2 || !isContinuation(s[index+1]) {
|
||||
return 0xfffd, 1
|
||||
}
|
||||
return (rune(x&0x1f) << 6) | (rune(s[index+1]) & 0x3f), 2
|
||||
r := (rune(x&0x1f) << 6) | (rune(s[index+1]) & 0x3f)
|
||||
if r >= 1<<7 {
|
||||
// Check whether the rune really needed to be encoded as a two-byte
|
||||
// sequence. UTF-8 requires every rune to be encoded in the smallest
|
||||
// sequence possible.
|
||||
return r, 2
|
||||
}
|
||||
case x&0xf0 == 0xe0: // 1110xxxx
|
||||
if remaining < 3 {
|
||||
if remaining < 3 || !isContinuation(s[index+1]) || !isContinuation(s[index+2]) {
|
||||
return 0xfffd, 1
|
||||
}
|
||||
return (rune(x&0x0f) << 12) | ((rune(s[index+1]) & 0x3f) << 6) | (rune(s[index+2]) & 0x3f), 3
|
||||
r := (rune(x&0x0f) << 12) | ((rune(s[index+1]) & 0x3f) << 6) | (rune(s[index+2]) & 0x3f)
|
||||
if r >= 1<<11 && !(r >= 0xD800 && r <= 0xDFFF) {
|
||||
// Check whether the rune really needed to be encoded as a
|
||||
// three-byte sequence and check that this is not a Unicode
|
||||
// surrogate pair (which are not allowed by UTF-8).
|
||||
return r, 3
|
||||
}
|
||||
case x&0xf8 == 0xf0: // 11110xxx
|
||||
if remaining < 4 {
|
||||
if remaining < 4 || !isContinuation(s[index+1]) || !isContinuation(s[index+2]) || !isContinuation(s[index+3]) {
|
||||
return 0xfffd, 1
|
||||
}
|
||||
return (rune(x&0x07) << 18) | ((rune(s[index+1]) & 0x3f) << 12) | ((rune(s[index+2]) & 0x3f) << 6) | (rune(s[index+3]) & 0x3f), 4
|
||||
default:
|
||||
return 0xfffd, 1
|
||||
r := (rune(x&0x07) << 18) | ((rune(s[index+1]) & 0x3f) << 12) | ((rune(s[index+2]) & 0x3f) << 6) | (rune(s[index+3]) & 0x3f)
|
||||
if r >= 1<<16 && r <= '\U0010FFFF' {
|
||||
// Check whether this rune really needed to be encoded as a four
|
||||
// byte sequence and check that the resulting rune is in the valid
|
||||
// range (up to at most U+10FFFF).
|
||||
return r, 4
|
||||
}
|
||||
}
|
||||
|
||||
// Failed to decode. Return the Unicode replacement character and a length of 1.
|
||||
return 0xfffd, 1
|
||||
}
|
||||
|
||||
// isContinuation returns true if (and only if) this is a UTF-8 continuation
|
||||
// byte.
|
||||
func isContinuation(b byte) bool {
|
||||
// Continuation bytes have their topmost bits set to 0b10.
|
||||
return b&0xc0 == 0x80
|
||||
}
|
||||
|
||||
@@ -4,11 +4,17 @@ package runtime
|
||||
|
||||
import "internal/bytealg"
|
||||
|
||||
// indexByte provides compatibility with Go 1.11.
|
||||
// The following functions provide compatibility with Go 1.11.
|
||||
// See the following:
|
||||
// https://github.com/tinygo-org/tinygo/issues/351
|
||||
// https://github.com/golang/go/commit/ad4a58e31501bce5de2aad90a620eaecdc1eecb8
|
||||
|
||||
//go:linkname indexByte strings.IndexByte
|
||||
func indexByte(s string, c byte) int {
|
||||
return bytealg.IndexByteString(s, c)
|
||||
}
|
||||
|
||||
//go:linkname bytesEqual bytes.Equal
|
||||
func bytesEqual(a, b []byte) bool {
|
||||
return bytealg.Equal(a, b)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// +build baremetal
|
||||
// +build baremetal wasi
|
||||
|
||||
package syscall
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build baremetal nintendoswitch
|
||||
// +build baremetal nintendoswitch wasi
|
||||
|
||||
package syscall
|
||||
|
||||
|
||||
@@ -20,3 +20,15 @@ type InternalBenchmark struct {
|
||||
Name string
|
||||
F func(b *B)
|
||||
}
|
||||
|
||||
func (b *B) SetBytes(n int64) {
|
||||
panic("testing: unimplemented: B.SetBytes")
|
||||
}
|
||||
|
||||
func (b *B) ResetTimer() {
|
||||
panic("testing: unimplemented: B.ResetTimer")
|
||||
}
|
||||
|
||||
func (b *B) Run(name string, f func(b *B)) bool {
|
||||
panic("testing: unimplemented: B.Run")
|
||||
}
|
||||
|
||||
+37
-2
@@ -42,7 +42,7 @@ type TB interface {
|
||||
SkipNow()
|
||||
Skipf(format string, args ...interface{})
|
||||
Skipped() bool
|
||||
// Helper()
|
||||
Helper()
|
||||
}
|
||||
|
||||
var _ TB = (*T)(nil)
|
||||
@@ -53,6 +53,7 @@ var _ TB = (*B)(nil)
|
||||
//
|
||||
type T struct {
|
||||
common
|
||||
indent string
|
||||
}
|
||||
|
||||
// Name returns the name of the running test or benchmark.
|
||||
@@ -154,6 +155,38 @@ func (c *common) Skipped() bool {
|
||||
return c.skipped
|
||||
}
|
||||
|
||||
// Helper is not implemented, it is only provided for compatibility.
|
||||
func (c *common) Helper() {
|
||||
// Unimplemented.
|
||||
}
|
||||
|
||||
// Run runs a subtest of f t called name. It waits until the subtest is finished
|
||||
// and returns whether the subtest succeeded.
|
||||
func (t *T) Run(name string, f func(t *T)) bool {
|
||||
// Create a subtest.
|
||||
sub := T{
|
||||
indent: t.indent + " ",
|
||||
common: common{
|
||||
name: t.name + "/" + name,
|
||||
output: &bytes.Buffer{},
|
||||
},
|
||||
}
|
||||
|
||||
// Run the test.
|
||||
fmt.Printf("=== RUN %s\n", sub.name)
|
||||
f(&sub)
|
||||
|
||||
// Process the result (pass or fail).
|
||||
if sub.failed {
|
||||
t.failed = true
|
||||
fmt.Printf(sub.indent+"--- FAIL: %s\n", sub.name)
|
||||
} else {
|
||||
fmt.Printf(sub.indent+"--- PASS: %s\n", sub.name)
|
||||
}
|
||||
fmt.Print(sub.output)
|
||||
return !sub.failed
|
||||
}
|
||||
|
||||
// InternalTest is a reference to a test that should be called during a test suite run.
|
||||
type InternalTest struct {
|
||||
Name string
|
||||
@@ -185,7 +218,7 @@ func (m *M) Run() int {
|
||||
} else {
|
||||
fmt.Printf("--- PASS: %s\n", test.Name)
|
||||
}
|
||||
fmt.Println(t.output)
|
||||
fmt.Print(t.output)
|
||||
|
||||
if t.failed {
|
||||
failures++
|
||||
@@ -195,6 +228,8 @@ func (m *M) Run() int {
|
||||
if failures > 0 {
|
||||
fmt.Printf("exit status %d\n", failures)
|
||||
fmt.Println("FAIL")
|
||||
} else {
|
||||
fmt.Println("PASS")
|
||||
}
|
||||
return failures
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"inherits": ["atsamd21g18a"],
|
||||
"build-tags": ["sam", "atsamd21g18a", "arduino_nano33"],
|
||||
"build-tags": ["arduino_nano33"],
|
||||
"flash-command": "bossac -i -e -w -v -R -U --port={port} --offset=0x2000 {bin}",
|
||||
"flash-1200-bps-reset": "true"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"inherits": ["atsamd21g18a"],
|
||||
"build-tags": ["sam", "atsamd21g18a", "arduino_zero"],
|
||||
"build-tags": ["arduino_zero"],
|
||||
"flash-command": "bossac -i -e -w -v -R -U --port={port} --offset=0x2000 {bin}",
|
||||
"flash-1200-bps-reset": "true"
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user