Compare commits

...

73 Commits

Author SHA1 Message Date
Ayke van Laethem 15361c829e main: release 0.16.0 2020-11-17 11:15:15 +01:00
Ayke van Laethem 3f680b75f3 sam: remove redundant build tags
Some build tags were duplicated. This commit removes them.
2020-11-15 16:19:51 +01:00
Ayke van Laethem 9a7e633997 teensy36: add to smoketest
This required some changes to the UART code to get it to compile on Go
1.11.
2020-11-15 13:08:36 +01:00
ardnew 39b1f8b6f5 teensy40: UART: add missing godocs, rename Flush to Sync 2020-11-15 12:34:15 +01:00
ardnew 9aa50853b8 teensy40: add UART support 2020-11-15 12:34:15 +01:00
Ayke van Laethem 9ca0e3f2d1 Makefile: fix issue with Go 1.15.5
For details, see https://github.com/golang/go/issues/42606
2020-11-14 15:04:11 +01:00
ardnew 3cdc110462 teensy40: use implicit const defs (PinMode/PinChange) 2020-11-13 07:53:16 +01:00
ardnew 7cc687d416 teensy40: Add GPIO external interrupt support 2020-11-13 07:53:16 +01:00
Ron Evans ce57a034c3 ci: update CircleCI, Azure, and Docker builds to Go 1.15
Signed-off-by: deadprogram <ron@hybridgroup.com>
2020-11-13 03:07:35 +01:00
ardnew 30bee3afef add better fault identification for Cortex-M3/M33/M4/M7 hardfault handlers, add fault description registers to SCB_Type 2020-11-11 18:34:47 +01:00
ardnew b1d24a72c1 teensy40: fix typo in target JSON 2020-11-11 18:34:47 +01:00
ardnew 6e24c86320 teensy40: remove FPU spec in target JSON list of cflags 2020-11-11 18:34:47 +01:00
ardnew 19a0270303 teensy40: refactor to remove unnecessary code and constants 2020-11-11 18:34:47 +01:00
ardnew 47410a4b54 teensy40: init RTC and use ARM cycle counter for improved SysTick accuracy 2020-11-11 18:34:47 +01:00
ardnew 0d9c46b59e teensy40: fix PIT clock, which actually uses 24 MHz OSC
see: https://forum.pjrc.com/threads/63979-What-peripherals-are-affected-by-the-undocumented-24-MHz-OSC-circuit-on-Teensy-4-0
2020-11-11 18:34:47 +01:00
ardnew f93b28057a mimxrt1062: move device-specific files to "device/nxp" package 2020-11-11 18:34:47 +01:00
ardnew 691185f5f4 teensy40: initial implementation 2020-11-11 18:34:47 +01:00
Ayke van Laethem 163df7670a main: update go-llvm to fix LLVM build tags for Linux
This should make TinyGo buildable again on Darwin with a Homebrew
installed LLVM.
2020-11-09 18:45:37 +01:00
deadprogram 77c70d2758 machine/qtpy: add board definition for Adafruit QTPy
Signed-off-by: deadprogram <ron@hybridgroup.com>
2020-11-08 22:56:01 +01:00
Ayke van Laethem 7c4e83f5c0 machine: clarify caller's responsibility in SetInterrupt 2020-11-08 15:11:50 +01:00
jypelle db27541b1a Fix #1483 2020-11-08 09:32:13 +01:00
tom-horn 3bb994da9f Allow interrupts in stm32f103xx (#1466)
machine/stm32f103xx: allow interrupts in stm32f103xx
2020-11-07 12:21:38 +01:00
Elliott Sales de Andrade b3bd891ee0 Make lib64 clang include path check more robust.
On Fedora 33+, there is a buggy package that installs to
`/usr/lib64/clang/{version}/lib`, even on 32-bit systems. The original
code sees the `/usr/lib64/clang/{version}` directory, checks for an
`include` subdirectory, and then gives up because it doesn't exist.

To be more robust, check both `/usr/lib64/clang/{version}/include` and
`/usr/lib/clang/{version}/include`, and only allow versions that match
the LLVM major version used to build tinygo.
2020-11-04 00:04:33 +01:00
Lucas Teske 387bca8e32 nintendoswitch: Add env parser and removed unused stuff
*	Heap allocation based on available ram
*	Added homebrew launcher parser (for overriden heap)
*	Removed unused stuff (moved to gonx)
*	Kept require code at minimum to work in a real device
*	Moved everything to a single file
2020-11-03 23:28:55 +01:00
Nia Weiss d424b3d7ea add missing return pointer restore for regular coroutine tail calls
This fixes an issue where a normal suspending call followed by a plain tail call would result in the tail return value being written to the return pointer of the normal suspending call.
This is fixed by saving the return pointer at the start of the function and restoring it before initiating a plain tail call.
2020-11-01 08:32:55 +01:00
deadprogram c20328472b make: fixes error detecting llvm-nm tool for wasi-libc build
Signed-off-by: deadprogram <ron@hybridgroup.com>
2020-11-01 01:12:39 +01:00
Ayke van Laethem 171f793c1e avr: properly support the .rodata section
Unfortunately, the .rodata section can't be stored in flash. Instead, an
explicit .progmem section should be used, which is supported in LLVM as
address space 1 but not exposed to normal programs.

Eventually a pass should be written that converts trivial const globals
of which all loads are visible to be in addrspace 1, to get the benefits
of storing those globals directly in ROM.
2020-10-31 21:06:26 +01:00
Nia Weiss 3364da6f25 improve autodetection of LLVM tooling
Previously, our autodetection would fail on LLVM 11.
This now checks all common names for LLVM 10 and 11.
2020-10-31 18:17:38 +01:00
Ayke van Laethem e99b8a24fe runtime: allow ranging over a nil map
This appears to be allowed by the specification, at least it is allowed
by the main Go implementation: https://play.golang.org/p/S8jxAMytKDB

Allow it in TinyGo too, for consistency.

Found because it is triggered with `tinygo test flags`. This doesn't
make the flags package pass all tests, but is a step closer.
2020-10-29 21:53:41 +01:00
Ayke van Laethem 69e1aa4878 testing: add Run method
This patch adds subtests via the Run function. This gets two more
packages to pass tests: encoding/base32 and hash/fnv.
2020-10-28 18:25:56 +01:00
Ayke van Laethem 7a78b2dc0e all: replace underscores with dashes in target names
This is the convention, so use it everywhere.
2020-10-28 12:40:54 +01:00
Ayke van Laethem 2b1d4ce96e main: update go.sum 2020-10-28 08:48:11 +01:00
Ayke van Laethem 3e40b08ba0 compiler: implement negate for complex numbers 2020-10-28 07:38:51 +01:00
Takeshi Yoneda ffeff55706 wasm: use the fixed length buffer for putchar
Signed-off-by: mathetake <takeshi@tetrate.io>
2020-10-23 22:04:32 +02:00
Takeshi Yoneda 1dec9dcbc4 implement reflect.Swapper
Signed-off-by: mathetake <takeshi@tetrate.io>
2020-10-23 21:37:35 +02:00
Martin Tournoij ff833ef998 Add os.LookupEnv() stub
os.Getenv() was already stubbed out, but os.LookupEnv() wasn't. This
will allow me to compile my program unmodified without using separate
files and build tags.
2020-10-23 14:39:15 +02:00
Connor 6eeebfeb5c WIP: Esp8266 Get Function (#1438)
machine/esp8266: add Pin Get() support
2020-10-22 20:58:44 +02:00
Ayke van Laethem 6ab0106af3 nrf: fix nrf52832 flash size
I've accidentally specified just half of the available flash in the
linker script. This change fixes that.

There is in fact a 256kB version of the nrf52832, but it also has 32kB
of RAM so if you had used that it wouldn't actually work right now.
Also, extending the available flash should not affect existing programs
(as I haven't seen any run into size limitations yet).
2020-10-20 19:13:43 +02:00
蒼時弦也 e690ff0d8c Add instanceof support for WebAssembly 2020-10-18 22:15:47 +02:00
Ayke van Laethem 06564cbdb2 Switch default frequency to 4MHz
Let's use the same default frequency everywhere, for consistency.
It could be any frequency, but 4MHz is already used for other chips and
it seems like a reasonable frequency to me (not too fast for most chips
but still reasonably fast). Oh, and 4MHz is slow enough that it can be
inspected by a Saleae Logic 4 (that sadly has been discontinued).
2020-10-18 22:14:21 +02:00
Ayke van Laethem 47dc76fc34 nrf: give more flexibility in picking SPI speeds
Instead of only allowing a limited number of speeds, use the provided
speed as an upper bound on the allowed speed. The reasoning is that
picking a higher speed than requrested will likely result in malfunction
while picking a lower speed will usually only result in slower
operation.
This behavior matches the ESP32 at least.
2020-10-18 22:11:03 +02:00
deadprogram d382f3a259 esp8266: add target for d1mini board and add pin mappings for SPI/I2C to help out implementers
Signed-off-by: deadprogram <ron@hybridgroup.com>
2020-10-17 19:57:53 +02:00
Ayke van Laethem 47dc1087e8 ci: work around bug in Go 1.15.3
This works around a bug in Go 1.15.3 by pinning an older version.
See: https://github.com/golang/go/issues/42032
2020-10-17 12:23:03 +02:00
deadprogram c7d8223ab7 machine/esp32, targets/esp32: correct board definitions for actual boards not processor variants, also define all labeled pins
Signed-off-by: deadprogram <ron@hybridgroup.com>
2020-10-14 21:48:48 +02:00
ardnew 3eb33dff5d feather-stm32f405: add I2C support (#1378)
* machine/stm32f405: add initial I2C support
2020-10-14 18:00:24 +02:00
deadprogram bb146edb47 wasi: remove --no-threads flag as no longer in LLVM 11 linker
Signed-off-by: deadprogram <ron@hybridgroup.com>
2020-10-14 13:58:01 +02:00
Nia Weiss ed9b97cc0d runtime: add cheap atomic condition variable 2020-10-14 13:35:00 +02:00
Ayke van Laethem b40f250530 main: add initial support for (in-development) LLVM 11
This can be useful to test improvements in LLVM master and to make it
possible to support LLVM 11 for the most part already before the next
release. That also allows catching LLVM bugs early to fix them upstream.

Note that tests do not yet pass for this LLVM version, but the TinyGo
compiler can be built with the binaries from apt.llvm.org (at the time
of making this commit).
2020-10-13 20:23:50 +02:00
ardnew 184175378f gen-device-svd: ensure enum bitfields are unique 2020-10-10 12:52:11 +02:00
Ayke van Laethem d8dbe5748a testing: implement some benchmark stubs
This allows the following packages to pass tests:

  * crypto/des
  * encoding/hex

I have not included crypto/rc4 as it doesn't pass tests on Go 1.11 (but
it works on later versions).
2020-10-09 15:22:19 +02:00
Lucas Teske c2bfe6bc8d arm64: Add support for system calls (SVC) 2020-10-03 20:07:51 +02:00
Takeshi Yoneda 9a015f4f64 add wasm-abi field in TargetSpec && set generic for WASI by default (#1421)
Signed-off-by: mathetake <takeshi@tetrate.io>
2020-10-03 19:52:01 +02:00
ardnew 9ad2315079 feather-stm32f405: add SPI support (#1377)
* machine/stm32f405: add SPI support
2020-10-02 20:05:58 +02:00
Ayke van Laethem 431e51b8a0 runtime: use dedicated printfloat32
It can be unexpected that printing a float32 involves 64-bit floating
point routines, see for example:
https://github.com/tinygo-org/tinygo/issues/1415

This commit adds a dedicated printfloat32 instead just for printing
float32 values. It comes with a possible code size increase, but only if
both float32 and float64 values are printed. Therefore, this should be
an improvement in almost all cases.

I also tried using printfloat32 for everything (and casting a float64 to
float32 to print) but the printed values are slightly different,
breaking the testdata/math.go test for example.
2020-10-02 11:26:22 +02:00
Ayke van Laethem 67de8b490d gc: use raw stack access whenever possible
The only architecture that actually needs special support for scanning
the stack is WebAssembly. All others allow raw access to the stack with
a small bit of assembly. Therefore, don't manually keep track of all
these objects on the stack manually and instead just use conservative
stack scanning.

This results in a massive code size decrease in the affected targets
(only tested linux/amd64 for code size) - sometimes around 33%. It also
allows for future improvements such as using proper stackful goroutines.
2020-10-02 08:54:43 +02:00
Ayke van Laethem bfa29f17da runtime: move/refactor some GC-related code
Instead of putting tinygo_scanCurrentStack in scheduler_*.S files, put
them in dedicated files. The function tinygo_scanCurrentStack has
nothing to do with scheduling and so doesn't belong there. Additionally,
while scheduling code is made specific for the Cortex-M, the
tinygo_scanCurrentStack is generic to all ARM targets so this move
removes some duplication there.

Specifically:

  * tinygo_scanCurrentStack is moved out of scheduler_cortexm.S as it
    isn't really part of the scheduler. It is now gc_arm.S.
  * Same for the AVR target.
  * Same for the RISCV target.
  * scheduler_gba.S is removed, using gc_arm.S instead as it only
    contains tinygo_scanCurrentStack.
2020-10-02 08:54:43 +02:00
Ayke van Laethem 7123941df0 main: add support for debugging qemu-user targets
This commit allows debugging like the following:

    GOARCH=arm tinygo gdb ./testdata/alias.go

This can be very useful to debug issues on a different instruction set
architecture but still on a host system.

I tested the following 7 configurations to make sure it works and I
didn't break anything:

    GOOS=amd64
    GOOS=386
    GOOS=arm
    GOOS=arm64
    tinygo gdb -target=hifive1-qemu
    tinygo gdb -target=cortex-m-qemu
    tinygo gdb -target=microbit
2020-10-02 08:54:43 +02:00
Ayke van Laethem 05d2f2c412 main: improve support for x86-32 and add tests
To avoid breaking this, make sure we actually test x86-32 (aka i386 aka
GOARCH=386) support in CI.

Also remove the now-unnecessary binutils-arm-none-eabi package to speed
up CI a bit.
2020-10-02 08:54:43 +02:00
Ayke van Laethem 9a12d129ab testing: implement dummy Helper method
This lets a few more packages pass tests: container/heap and
encoding/ascii85.
2020-10-01 02:14:59 +02:00
Ayke van Laethem 0ecfe9eade ci: fix make wasmtest
This fixes issue https://github.com/tinygo-org/tinygo/issues/1418. In
short, it appears there was a race condition that was only visible on
GOARCH=386 but not on GOARCH=amd64. Updating to a more recent chromedp
version fixes the issue.
2020-10-01 02:07:00 +02:00
Takeshi Yoneda f50ad3585d support WASI target (#1373)
* initial commit for WASI support

* merge "time" package with wasi build tag
* override syscall package with wasi build tag
* create runtime_wasm_{js,wasi}.go files
* create syscall_wasi.go file
* create time/zoneinfo_wasi.go file as the replacement of zoneinfo_js.go
* add targets/wasi.json target

* set visbility hidden for runtime extern variables

Accodring to the WASI docs (https://github.com/WebAssembly/WASI/blob/master/design/application-abi.md#current-unstable-abi),
none of exports of WASI executable(Command) should no be accessed.

v0.19.0 of bytecodealliance/wasmetime, which is often refered to as the reference implementation of WASI,
does not accept any exports except functions and the only limited variables like "table", "memory".

* merge syscall_{baremetal,wasi}.go

* fix js target build

* mv wasi functions to syscall/wasi && implement sleepTicks

* WASI: set visibility hidden for globals variables

* mv back syscall/wasi/* to runtime package

* WASI: add test

* unexport wasi types

* WASI test: fix wasmtime path

* stop changing visibility of runtime.alloc

* use GOOS=linux, GOARCH=arm for wasi target

Signed-off-by: mathetake <takeshi@tetrate.io>

* WASI: fix build tags for os/runtime packages

Signed-off-by: mathetake <takeshi@tetrate.io>

* run WASI test only on Linux

Signed-off-by: mathetake <takeshi@tetrate.io>

* set InternalLinkage instead of changing visibility

Signed-off-by: mathetake <takeshi@tetrate.io>
2020-09-29 21:58:03 +02:00
Ayke van Laethem d39c7abb4d nrf: fix double stop signal in I2C 2020-09-27 15:21:54 +02:00
Daniel M. Lambea 9e61e6fe4d nrf: add I2C error checking (#1392)
* machine/nrf: add I2C error checking
2020-09-26 09:20:43 +02:00
Lucas Teske d1f90ef59c nintendoswitch: fix crash when printing long lines (> 120) 2020-09-26 02:52:10 +02:00
Ayke van Laethem 54602fe0c3 main: add support for -c and -o flags to tinygo test 2020-09-25 16:18:10 +02:00
Ayke van Laethem c10dcd429c main: refactor -o flag 2020-09-25 16:18:10 +02:00
Ayke van Laethem b713001313 test: support non-host tests
For example, for running tests with -target=wasm or
-target=cortex-m-qemu. It looks at the output to determine whether tests
were successful in the absence of a status code.
2020-09-24 21:17:26 +02:00
Ayke van Laethem 1096596b69 compiler: fix floating point bugs
There were a few bugs related to floating point. After fixing these, the
math package started passing all tests.
2020-09-21 10:43:46 +02:00
Ayke van Laethem 7b601b3e3c loader: fix linkname in test binaries
This is an issue in particular in the math package, of which most
functions are defined in the runtime package.
2020-09-21 10:43:46 +02:00
Ayke van Laethem ec54e7763d runtime: fix UTF-8 decoding
The algorithm now checks for invalid UTF-8 sequences, which is required
by the Go spec.

This gets the tests of the unicode/utf8 package to pass.

Also add bytes.Equal for Go 1.11, which again is necessary for the
unicode/utf8 package.
2020-09-21 08:49:13 +02:00
Elliott Sales de Andrade 41afb77080 builder: also check lib64 for clang include path.
On 64-bit Fedora, `lib64` is where the clang headers are, not `lib`. For
multiarch systems, both will exist, but it's likely you want 64-bit, so
check that first.
2020-09-20 14:00:02 +02:00
Jacques Supcik 13fe668929 compileopts: simplify copyProperties using reflection 2020-09-20 13:49:16 +02:00
sago35 2a72262c33 version: update TinyGo version to 0.16.0-dev 2020-09-18 01:32:31 +02:00
157 changed files with 6972 additions and 769 deletions
+16 -5
View File
@@ -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
+54
View File
@@ -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
View File
@@ -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 && \
+25 -25
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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 -1
View File
@@ -1,5 +1,5 @@
// +build !byollvm
// +build !llvm9
// +build !llvm9,!llvm11
package cgo
+14
View File
@@ -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
View File
@@ -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
View File
@@ -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
+68 -1
View File
@@ -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
View File
@@ -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())
}
+38
View File
@@ -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
+3 -3
View File
@@ -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
)
+10 -8
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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 {
+92 -32
View File
@@ -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
View File
@@ -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
-35
View File
@@ -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
+431
View File
@@ -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.
)
+36
View File
@@ -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
+29
View File
@@ -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
)
+529
View File
@@ -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")
}
}
+29
View File
@@ -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
)
+278
View File
@@ -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)
}
}
}
+88
View File
@@ -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
)
-6
View File
@@ -1,6 +0,0 @@
// +build esp32_wroom_32
package machine
// Blue LED on the ESP32-WROOM-32 module.
const LED = Pin(2)
+36 -4
View File
@@ -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() {}
+14
View File
@@ -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
)
+118
View File
@@ -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
)
+262
View File
@@ -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
View File
@@ -1,4 +1,4 @@
// +build avr nrf sam stm32,!stm32f4 fe310 k210
// +build avr nrf sam stm32,!stm32f407 fe310 k210
package machine
+2 -1
View File
@@ -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
+5 -3
View File
@@ -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).
+1 -1
View File
@@ -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.
+9
View File
@@ -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 {
+1 -1
View File
@@ -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;
+3 -2
View File
@@ -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
+881
View File
@@ -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")
}
}
+325
View File
@@ -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
View File
@@ -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)
+481
View File
@@ -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
}
+78 -40
View File
@@ -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 n1 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
}
+113 -2
View File
@@ -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
}
}
}
+14 -16
View File
@@ -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
}
+4
View File
@@ -3,3 +3,7 @@ package os
func Getenv(key string) string {
return ""
}
func LookupEnv(key string) (string, bool) {
return "", false
}
+1 -1
View File
@@ -1,4 +1,4 @@
// +build darwin linux,!baremetal freebsd,!baremetal
// +build darwin linux,!baremetal,!wasi freebsd,!baremetal
package os
+36 -1
View File
@@ -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)
}
}
+5 -1
View File
@@ -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)
}
+5 -1
View File
@@ -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 -1
View File
@@ -1,4 +1,4 @@
// +build arm,!baremetal arm,arm7tdmi
// +build arm,!baremetal,!wasm arm,arm7tdmi
package runtime
+5 -2
View File
@@ -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)
}
+5
View File
@@ -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
+90
View File
@@ -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(&notifiedPlaceholder)) {
return true
}
case &notifiedPlaceholder:
// 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 &notifiedPlaceholder:
// 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 &notifiedPlaceholder:
// 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")
}
}
}
+38
View File
@@ -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()
}
}
+7
View File
@@ -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))
+22
View File
@@ -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
+29
View File
@@ -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
+23
View File
@@ -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
+52
View File
@@ -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 -1
View File
@@ -1,5 +1,5 @@
// +build gc.conservative gc.extalloc
// +build !baremetal
// +build wasm
package runtime
+1 -1
View File
@@ -1,5 +1,5 @@
// +build gc.conservative gc.extalloc
// +build baremetal
// +build !wasm
package runtime
+7
View File
@@ -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
View File
@@ -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 -1
View File
@@ -1,4 +1,4 @@
// +build cortexm,!nxp
// +build cortexm,!nxp,!qemu
package runtime
+1 -1
View File
@@ -1,4 +1,4 @@
// +build cortexm,!nxp
// +build atsamd21 nrf51
package runtime
+55 -26
View File
@@ -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
}
}
+12
View File
@@ -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")
}
}
+145
View File
@@ -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")
}
+330
View File
@@ -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) //
}
+49
View File
@@ -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)
}
+162
View File
@@ -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
}
+202 -9
View File
@@ -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
+33 -38
View File
@@ -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() {}
-22
View File
@@ -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)
+17 -5
View File
@@ -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) {
+14 -2
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -1,4 +1,4 @@
// +build darwin linux,!baremetal freebsd,!baremetal
// +build darwin linux,!baremetal,!wasi freebsd,!baremetal
// +build !nintendoswitch
+23 -66
View File
@@ -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()
+59
View File
@@ -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
+117
View File
@@ -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
}
}
)
-53
View File
@@ -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
-31
View File
@@ -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
View File
@@ -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
}
+7 -1
View File
@@ -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 -1
View File
@@ -1,4 +1,4 @@
// +build baremetal
// +build baremetal wasi
package syscall
+1 -1
View File
@@ -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
+12
View File
@@ -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
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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