Compare commits

...

76 Commits

Author SHA1 Message Date
Ayke van Laethem 154d4a781f main: release 0.14.0 2020-08-03 12:46:32 +02:00
deadprogram b5ab114514 dockerhub: use post checkout hook for git submodule init
Signed-off-by: deadprogram <ron@hybridgroup.com>
2020-08-03 08:30:31 +02:00
BCG 0a7e74045a feather-nrf52840: corrected USB identifier constants 2020-08-01 10:55:33 +02:00
Ayke van Laethem f05b378b89 compiler: add proper parameter names to runtime.initAll
This is required by the coroutines pass, otherwise it will panic. It
checks for the proper parameter names to make sure the function is not
exported. In this case, the runtime.initAll function wasn't exported but
simply didn't have the correct parameter names so the check triggered
even though it shouldn't.
2020-07-31 17:34:44 +02:00
Ayke van Laethem 888ca4ab0c interp: fix sync/atomic.Value load/store methods
These methods do some unsafe pointer casting but can be assumed to not
have significant side effects. Simply call these functions at runtime
instead of compile time.

This is a partial fix for importing image/png.
2020-07-31 17:34:44 +02:00
deadprogram 903bebd071 docs: add Nintendo Switch to list of supported boards/devices
Signed-off-by: deadprogram <ron@hybridgroup.com>
2020-07-31 09:12:44 +02:00
waj334 848c3e55a9 compiler: implement func value and builtin defers
Co-authored-by: Justin A. Wilson <maker.pro.game@gmail.com>
2020-07-31 01:48:57 +02:00
Lucas Teske 3650c2c739 nintendoswitch: Add experimental Nintendo Switch support without CRT
Bare minimal nintendo switch support using LLD
2020-07-31 00:58:09 +02:00
Ayke van Laethem d4e04e4e49 compiler: fix named string to []byte slice conversion
This was missing a `.Underlying()` call to avoid testing the named type
(but instead test for the underlying type).
2020-07-29 12:13:37 +02:00
Ayke van Laethem e41e5106cc main: add -target flag to tests
This makes it easy to test one particular architecture, for example:

    go test -v -target=hifive1-qemu

This speeds up testing and allows testing targets that are not included
in the test by default (such as RISC-V tests on Linux).
2020-07-24 16:59:37 +02:00
Ayke van Laethem ca03b8d442 ci: fix Windows QEMU version
It appears that version 2020.07.22 or 2020.07.23 introduced a breaking
change in RISC-V. We will have to fix this eventually, but for now it's
easiest to just pin the QEMU version. Once this new QEMU version
(version 5?) is more widely available, it becomes easier to debug and
fix the underlying cause.
2020-07-24 08:24:20 +02:00
deadprogram d1c4ed664e all: changeover to eliminate all direct use of master/slave terminology
Signed-off-by: deadprogram <ron@hybridgroup.com>
2020-07-23 22:45:23 +02:00
Ayke van Laethem fdaddf6917 ci: do not cache TinyGo cache dir
It doesn't seem to speed up the build and it causes issues with a stale
cache.
2020-07-23 21:49:20 +02:00
Ayke van Laethem 50a677e9b7 arm: use CFI directives for stack usage
Call Frame Information is stored in the .debug_frame section and is used
by debuggers for unwinding. For assembly, this information is not known.
Debuggers will normally use heuristics to figure out the parent function
in the absence of call frame information.

This usually works fine, but is not enough for determining stack sizes.
Instead, I hardcoded the stack size information in
stacksize/stacksize.go, which is somewhat fragile. This change uses CFI
assembly directives to store this information instead of hardcoding it.

This change also fixes the following error message that would appear in
GDB:

    Backtrace stopped: previous frame identical to this frame (corrupt stack?)

More information on CFI:
  * https://sourceware.org/binutils/docs/as/CFI-directives.html
  * https://www.imperialviolet.org/2017/01/18/cfi.html
2020-07-20 17:36:50 +02:00
Ethan Reesor 6ad6f14a04 Use a jump table instead of if-then-else 2020-07-18 08:39:26 -04:00
Jaden Weiss 19e0f4709e transform: track 0-index GEPs
It appears that LLVM is turning bitcasts into 0-index GEPs.
This caused stuff to not be tracked, resulting in use-after-free issues.
This solution is sub-optimal, but is the most reasonable solution I could come up with without redesigning the stack slots pass.
2020-07-16 20:50:23 +02:00
Jaden Weiss ae5b297d59 builder: remove optimization level 0
Currently, turning optimizations off causes compile failures.
We rely on the optimizer removing some dead symbols.
Avoid providing an option that does not work right now.
In the future once everything has been fixed we can re-enable this.
2020-07-16 16:41:52 +02:00
Ethan Reesor ca1a282495 Use runtime/volatile.T.ReplaceBits 2020-07-14 06:08:08 +02:00
deadprogram 01f5c51b77 machine/feather-nrf52840: add smoketest for Adafruit Feather nrf52840 board
Signed-off-by: deadprogram <ron@hybridgroup.com>
2020-07-14 00:13:10 +02:00
BCG ad6adfd8ff Added board definition for Feather nRF52840 Express 2020-07-13 16:50:06 +02:00
Ethan Reesor 9815628930 Cleanup Teensy 3.6 linker script 2020-07-13 12:35:53 +02:00
Ayke van Laethem 05495c4282 all: fix -gc=none
This option was broken for a long time, in part because we didn't test
for it. This commit fixes that and adds a test to make sure it won't
break again unnoticed.
2020-07-13 12:20:09 +02:00
Ayke van Laethem d606315515 builder: try to determine stack size information at compile time
For now, this is just an extra flag that can be used to print stack
frame information, but this is intended to provide a way to determine
stack sizes for goroutines at compile time in many cases.

Stack sizes are often somewhere around 350 bytes so are in fact not all
that big usually. Once this can be determined at compile time in many
cases, it is possible to use this information when available and as a
result increase the fallback stack size if the size cannot be determined
at compile time. This should reduce stack overflows while at the same
time reducing RAM consumption in many cases.

Interesting output for testdata/channel.go:

    function                                 stack usage (in bytes)
    Reset_Handler                            332
    .Lcommand-line-arguments.fastreceiver    220
    .Lcommand-line-arguments.fastsender      192
    .Lcommand-line-arguments.iterator        192
    .Lcommand-line-arguments.main$1          184
    .Lcommand-line-arguments.main$2          200
    .Lcommand-line-arguments.main$3          200
    .Lcommand-line-arguments.main$4          328
    .Lcommand-line-arguments.receive         176
    .Lcommand-line-arguments.selectDeadlock  72
    .Lcommand-line-arguments.selectNoOp      72
    .Lcommand-line-arguments.send            184
    .Lcommand-line-arguments.sendComplex     192
    .Lcommand-line-arguments.sender          192
    .Lruntime.run$1                          548

This shows that the stack size (if these numbers are correct) can in
fact be determined automatically in many cases, especially for small
goroutines. One of the great things about Go is lightweight goroutines,
and reducing stack sizes is very important to make goroutines
lightweight on microcontrollers.
2020-07-11 14:47:43 +02:00
sago35 60fdf81209 docs: add MAix BiT and Teensy 3.6 to list of supported boards (#1230)
* docs: add MAix BiT and Teensy 3.6 to list of supported boards
2020-07-11 09:21:16 +02:00
Ayke van Laethem 39433a3553 compileopts: automatically add -g flag when including debug symbols
Debug information is often useful and there is no reason to include it
for Go code but not for C code. Also, disabling debug information should
disable it entirely, not just for Go code.
2020-07-10 16:56:13 +02:00
Ethan Reesor 04d097f4ea Implement custom abort and fault handler for debugging 2020-07-08 21:58:15 +02:00
Ethan Reesor 4750635a20 Viable NXP/Teensy support
- Fix UART & putChar
- Timer-based sleep
- Enable systick in abort
- Buffered, interrupt-based UART TX
- Use the new interrupt API and fix sleepTicks
- Make pins behave more like other boards
- Use the MCU's UART numbering
- Allow interrupts to wake the scheduler (#1214)
2020-07-08 21:58:15 +02:00
Ethan Reesor 59218cd784 Working on NXP/Teensy support 2020-07-08 21:58:15 +02:00
Ethan Reesor 079a789d49 Minimal NXP/Teensy support 2020-07-08 21:58:15 +02:00
deadprogram ca8e1b075a targets/maixbit: cleanup output from kflash command by removing ansi colors
Signed-off-by: deadprogram <ron@hybridgroup.com>
2020-07-08 20:16:03 +02:00
Branden Timm 33024d4aa2 Fix portL mappings for atmega2560 (#1222)
* machine/atmega2560: fix portL mapping for atmega2560
2020-07-08 19:02:10 +02:00
Branden Timm 49df129ccd docs: add submodule update step prior to 'make release' (#1213)
* docs: add submodule update step prior to 'make release'
2020-07-08 17:37:43 +02:00
Ayke van Laethem 3088dcadec building: add links to tinygo.org
The BUILDING.md file is not intended for developer builds but for
release builds. The website contains more specific and more complete
information on how to build TinyGo, so provide links to these pages.

The Windows link doesn't work yet, but should work with the next
release when we update the website.
2020-07-08 17:35:31 +02:00
Yannis Huber 7ed7e6cb11 risc-v: disable linker relaxations during gp init 2020-07-08 01:58:12 +02:00
Yannis Huber 0b94e486c1 maixbit: changes according to feedback 2020-07-08 00:21:59 +02:00
Yannis Huber 5ff76aacab runtime: reuse common code between 32 and 64-bit RISC-V 2020-07-08 00:21:59 +02:00
Yannis Huber 3ee7599a09 maixbit: use custom linker script
This linker script does not offer stack overflow protection
because the stack cannot be placed at the bottom of the RAM.
2020-07-08 00:21:59 +02:00
Yannis Huber 43a66b39cc riscv: refactor assembly files to support RV64 and F extension 2020-07-08 00:21:59 +02:00
Yannis Huber 66b21b4c86 maixbit (interruptions): fix fpioa function test 2020-07-08 00:21:59 +02:00
Yannis Huber a9568932be maixbit: workaround to avoid medium code model 2020-07-08 00:21:59 +02:00
Yannis Huber f2fbd1dd7e maixbit (gpio): fix pin configuration 2020-07-08 00:21:59 +02:00
Yannis Huber 21a9aa8102 maixbit (i2c): fix rx fifo buffer length 2020-07-08 00:21:59 +02:00
Yannis Huber e1757e0347 builder: add support for 64-bit RISC-V 2020-07-08 00:21:59 +02:00
Yannis Huber a05fc10699 maixbit: add smoke test 2020-07-08 00:21:59 +02:00
Yannis Huber a685217743 maixbit: add I2C support 2020-07-08 00:21:59 +02:00
Yannis Huber ad0c15080a maixbit: add SPI support 2020-07-08 00:21:59 +02:00
Yannis Huber 5446c6927e maixbit: add GPIOHS pin interrupt support 2020-07-08 00:21:59 +02:00
Yannis Huber 53c83fa445 maixbit: support both GPIO and GPIOHS controllers 2020-07-08 00:21:59 +02:00
Yannis Huber 804dc8b1f9 maixbit: init fpioa clock at reset 2020-07-08 00:21:59 +02:00
Yannis Huber e1ceca1931 maixbit: remove atomic operations 2020-07-08 00:21:59 +02:00
Yannis Huber 6620c4d2aa maixbit: add chip datasheet link and reformat code 2020-07-08 00:21:59 +02:00
Yannis Huber ccc604d2e0 riscv: fix offset in 64bit scheduler
Also keep common start.S file for 64 and 32 bit architectures.
2020-07-08 00:21:59 +02:00
Yannis Huber dfab1aa717 maixbit (uart): serial is working with echo example 2020-07-08 00:21:59 +02:00
Yannis Huber 75bcbbe6d8 riscv: align stack and data sections to 8 bytes
Alignment on 4 bytes can cause load/store address misalignment
exceptions when loading/storing 64bit values on the stack.
2020-07-08 00:21:59 +02:00
Yannis Huber d599959711 maixbit (uart): working on data tx
When the data to send is too long the program gives an exception.
2020-07-08 00:21:59 +02:00
Yannis Huber 7814964693 maixbit: add board definition and dummy runtime 2020-07-08 00:21:59 +02:00
Yannis Huber 2fe4a9be71 maix-bit: add code model in target definition
This is needed to avoid linking errors because the globals are placed
in memory at address 0x80000000 which is out of bounds for the default
code model.
2020-07-08 00:21:59 +02:00
Yannis Huber 163631df9e cmsis-svd: change submodule url to the TinyGo fork 2020-07-08 00:21:59 +02:00
Yannis Huber 9ad96fd809 Changes according to @aykevl's feedback 2020-07-08 00:21:59 +02:00
Yannis Huber 4a658b9082 Add llvm code model option in target definition 2020-07-08 00:21:59 +02:00
Yannis Huber 34e0961a79 Split RISC-V targets into 32/64-bit 2020-07-08 00:21:59 +02:00
Yannis Huber 875d36cba0 Add new kendryte k210 target definition 2020-07-08 00:21:59 +02:00
sago35 1a6bed3305 machine/samd51: add DAC support (#1198)
* machine/samd51: add DAC support
2020-07-06 14:02:51 +02:00
Branden Timm e0b9b1ecd1 machine: fix atmega2560 mapping for pins D2 and D5 2020-07-05 21:18:20 +02:00
Johan Brandhorst 149c9533e2 ci: add archlinux release job
Adds the arch-release job, which automatically updates
the tinygo-bin AUR package on every new git tag with
a semver version.
2020-07-05 09:51:44 +02:00
Ron Evans a85df334e6 machine/samd21: basic implementation for DAC (#1183)
* machine/samd21: basic DAC implementation

Signed-off-by: Ron Evans <ron@hybridgroup.com>
2020-07-04 18:16:25 +02:00
Jaden Weiss 89a9c09af5 runtime (atsamd51): allow interrupts to wake the scheduler 2020-07-04 15:00:44 +02:00
Ayke van Laethem 1451eeaf41 machine: change machine.Pin type to uint8
The `machine.Pin` type was a int8, which works fine but limits the
number of pin numbers to 127. This patch changes the type to uint8 and
changes NoPin to 0xff, which allows more pins to be used.

Some boards might not have that many pins but their internal
organization requires more pin numbers to be used (because it is
organized in pin ports and not all pins in a port have a physical
connection). Therefore the range of a int8 is too low to address these
higher pins.

This patch also has the surprising side effect of reducing binary size
in a number of cases. If there is a reduction it's usually just a few
bytes, with one outlier: the driver example amg88xx when compiled for
the pybadge board. I have not seen any increases in binary size.
2020-07-04 09:46:12 +02:00
Jaden Weiss e8c84d24a0 runtime (gc): do not scan the runqueue when the platform is not baremetal with a scheduler 2020-07-04 08:34:39 +02:00
Jaden Weiss a4f3457747 runtime: make channels work in interrupts 2020-07-04 08:34:39 +02:00
Ayke van Laethem aa3481e06a avr: fix target triple
It was `avr-atmel-none`, which is incorrect. It must be
`avr-unknown-unknown`.

Additionally, there is no reason to specify the target triple per chip,
it can be done for all AVR chips at once as it doesn't vary like
Cortex-M chips.
2020-06-30 20:48:42 +02:00
Hiroki Noda 2136cb2f59 Building self-built LLVM faster
Disable LIBEDIT/Z3/OCAMLDOC in LLVM build and use shallow-clone.
2020-06-30 19:09:23 +02:00
Ayke van Laethem acb3cfba6d avr: work around codegen bug in LLVM 10
Commit fc4857e98c (runtime: avoid recursion in printuint64 function)
caused a regression for AVR. I have tried locally with LLVM 11 (which
contains a number of codegen bugs) and the issue is no longer present,
so I'm assuming it's a codegen bug that is now fixed. However, LLVM 11
is not yet released so it seems best to me to work around this
temporarily (for the next few months).

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

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