Compare commits

...

20 Commits

Author SHA1 Message Date
Ayke van Laethem e0bdf2b070 WIP x509 on macOS 2025-08-04 14:27:20 +02:00
Dmitrii Sharshakov 0964176b4d chore: correct GOOS=js name in error messages for WASM 2025-08-03 11:47:57 +02:00
Elliott Sales de Andrade 1ffa9a4adf Makefile: Install missing dlmalloc files
Running tests against an installed TinyGoRoot fails with:
```
=== CONT  TestBuild/WebAssembly/gc.go-boehm
    main_test.go:441: wasi-libc: did not find any files for pattern builder.filePattern{glob:"dlmalloc/src/dlmalloc.c", exclude:[]string(nil)}
```
because these files are not there, and are required with Boehm GC.
2025-07-31 12:26:56 +02:00
Damian Gryski 8c5886060f internal/gclayout: make gclayout values constants
The previous versions calculated at init() prevented `interp` from running
in many cases, increasing compile times due to the increased need to revert
the partially interpreted results and also increasing binary runtime because
fewer optimizations had happened during interp.
2025-07-22 18:57:55 +02:00
Elliott Sales de Andrade 3bb092d4d4 Add flag to skip Renesas SVD builds
Much like the STMicro SVDs, Renesas SVDs are fully proprietary and not
under an FOSS license.
2025-07-20 12:15:38 +02:00
Ayke van Laethem 20e62dea6f stm32: add support for the STM32L031G6U6 2025-07-17 16:35:05 +02:00
Elias Naur 1b5d312c68 tests: de-flake goroutines test 2025-07-17 15:40:01 +02:00
diwamoto 435ddc5f2d machine: add international keys 2025-07-16 17:30:54 +02:00
张之阳 1de1f87c6b Docs: Clarify build verification step for macOS users 2025-07-12 09:23:08 +02:00
Ayke van Laethem 778164c98e machine: remove some unnecessary "// peripherals:" comments
These things are specified in the shared chip Go file, not in the board
pin aliases.
2025-07-11 10:28:38 +02:00
Ayke van Laethem b3da00ac1f machine: add I2C pin comments
Similar to PWM, I2C can only be used on some pins. To automatically
generate this information per board, we need to add extra comments that
can then be interpreted by doc-gen for the tinygo.org website.
2025-07-11 10:28:38 +02:00
Ayke van Laethem e454ad1b61 machine: standardize I2C errors with "i2c:" prefix
This probably looks better anyway.
2025-07-11 09:25:48 +02:00
Ayke van Laethem f845b469b1 machine: make I2C usable in the simulator
This fixes/improves a few issues with I2C support:

  * Validate I2C pins, so only pins that are supported by the hardware
    can be used (similar to how it's done with PWM).
  * Add address to Tx API (without it, the simulator can't really
    simulate I2C).
  * Add frequency when configuring. Not currently used, but might be
    useful in the future and adding it now avoids possibly breaking
    changes.

This is a breaking change, but since the simulator doesn't support I2C
yet that seems fine to me. (It does in my local changes, but those need
to be cleaned up before I can push them).
2025-07-11 09:25:48 +02:00
deadprogram 35adbffa54 fix: additional params to create chromium browser for testing
Signed-off-by: deadprogram <ron@hybridgroup.com>
2025-07-10 11:47:37 +02:00
emricks 01f3d3eb59 fix: add SPI and I2C to teensy 4.1 (#4943)
* fix: add SPI and I2C to teensy 4.1
* fix: add SPI3 variables back
* fix: formatting

Signed-off-by: Emrick Sorensen <emrickishere@gmail.com>
2025-07-04 08:46:48 +02:00
Ayke van Laethem 0e43146d32 darwin: add threading support and use it by default 2025-06-30 09:07:54 +02:00
Ayke van Laethem 93f40992c1 internal/task: a few small correctness fixes
This shouldn't affect Linux or MacOS, but it's good to have them fixed.
2025-06-30 09:07:54 +02:00
Elias Naur c6b47fe6a0 rp2: use the correct channel mask for rp2350 ADC; hold lock during read (#4938) 2025-06-29 15:20:58 -03:00
Elias Naur 536deaa00a rp2: disable digital input for analog inputs
This is what the Pico SDK does[0] and may fix #4936.

[0] https://github.com/raspberrypi/pico-sdk/blob/ee68c78d0afae2b69c03ae1a72bf5cc267a2d94c/src/rp2_common/hardware_adc/include/hardware/adc.h#L101
2025-06-28 09:34:06 +02:00
deadprogram df1d639deb chore: update version for 0.39 development cycle
Signed-off-by: deadprogram <ron@hybridgroup.com>
2025-06-21 19:13:13 +02:00
41 changed files with 520 additions and 397 deletions
+8 -2
View File
@@ -85,11 +85,17 @@ Try running TinyGo:
./build/tinygo help
Also, make sure the `tinygo` binary really is statically linked. Check this
using `ldd` (not to be confused with `lld`):
Also, make sure the `tinygo` binary really is statically linked. The command to check for
dynamic dependencies differs depending on your operating system.
On Linux, use `ldd` (not to be confused with `lld`):
ldd ./build/tinygo
On macOS, use otool -L:
otool -L ./build/tinygo
The result should not contain libclang or libLLVM.
## Make a release tarball
+9 -2
View File
@@ -187,7 +187,10 @@ fmt-check: ## Warn if any source needs reformatting
@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-esp gen-device-nrf gen-device-sam gen-device-sifive gen-device-kendryte gen-device-nxp gen-device-rp gen-device-renesas ## Generate microcontroller-specific sources
gen-device: gen-device-avr gen-device-esp gen-device-nrf gen-device-sam gen-device-sifive gen-device-kendryte gen-device-nxp gen-device-rp ## Generate microcontroller-specific sources
ifneq ($(RENESAS), 0)
gen-device: gen-device-renesas
endif
ifneq ($(STM32), 0)
gen-device: gen-device-stm32
endif
@@ -837,6 +840,8 @@ ifneq ($(STM32), 0)
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=mksnanov3 examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=stm32l0x1 examples/serial
@$(MD5SUM) test.hex
endif
$(TINYGO) build -size short -o test.hex -target=atmega328pb examples/blinkm
@$(MD5SUM) test.hex
@@ -907,7 +912,7 @@ endif
$(TINYGO) build -size short -o test.hex -target=hw-651 examples/machinetest
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=hw-651-s110v8 examples/machinetest
@$(MD5SUM) test.hex
@$(MD5SUM) test.hex
ifneq ($(WASM), 0)
$(TINYGO) build -size short -o wasm.wasm -target=wasm examples/wasm/export
$(TINYGO) build -size short -o wasm.wasm -target=wasm examples/wasm/main
@@ -958,6 +963,7 @@ build/release: tinygo gen-device $(if $(filter 1,$(USE_SYSTEM_BINARYEN)),,binary
@mkdir -p build/release/tinygo/lib/nrfx
@mkdir -p build/release/tinygo/lib/picolibc/newlib/libc
@mkdir -p build/release/tinygo/lib/picolibc/newlib/libm
@mkdir -p build/release/tinygo/lib/wasi-libc/dlmalloc
@mkdir -p build/release/tinygo/lib/wasi-libc/libc-bottom-half
@mkdir -p build/release/tinygo/lib/wasi-libc/libc-top-half/musl/arch
@mkdir -p build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src
@@ -1029,6 +1035,7 @@ endif
@cp -rp lib/picolibc/newlib/libm/common build/release/tinygo/lib/picolibc/newlib/libm
@cp -rp lib/picolibc/newlib/libm/math build/release/tinygo/lib/picolibc/newlib/libm
@cp -rp lib/picolibc-stdio.c build/release/tinygo/lib
@cp -rp lib/wasi-libc/dlmalloc/src build/release/tinygo/lib/wasi-libc/dlmalloc
@cp -rp lib/wasi-libc/libc-bottom-half/cloudlibc build/release/tinygo/lib/wasi-libc/libc-bottom-half
@cp -rp lib/wasi-libc/libc-bottom-half/headers build/release/tinygo/lib/wasi-libc/libc-bottom-half
@cp -rp lib/wasi-libc/libc-bottom-half/sources build/release/tinygo/lib/wasi-libc/libc-bottom-half
+4 -3
View File
@@ -189,7 +189,7 @@ func LoadTarget(options *Options) (*TargetSpec, error) {
case "wasip2":
options.Target = "wasip2"
default:
return nil, errors.New("GOARCH=wasm but GOOS is not set correctly. Please set GOOS to wasm, wasip1, or wasip2.")
return nil, errors.New("GOARCH=wasm but GOOS is not set correctly. Please set GOOS to js, wasip1, or wasip2.")
}
}
@@ -369,7 +369,7 @@ func defaultTarget(options *Options) (*TargetSpec, error) {
return nil, fmt.Errorf("invalid GOMIPS=%s: must be hardfloat or softfloat", options.GOMIPS)
}
case "wasm":
return nil, fmt.Errorf("GOARCH=wasm but GOOS is unset. Please set GOOS to wasm, wasip1, or wasip2.")
return nil, fmt.Errorf("GOARCH=wasm but GOOS is unset. Please set GOOS to js, wasip1, or wasip2.")
default:
return nil, fmt.Errorf("unknown GOARCH=%s", options.GOARCH)
}
@@ -385,7 +385,7 @@ func defaultTarget(options *Options) (*TargetSpec, error) {
platformVersion = "11.0.0" // first macosx platform with arm64 support
}
llvmvendor = "apple"
spec.Scheduler = "tasks"
spec.Scheduler = "threads"
spec.Linker = "ld.lld"
spec.Libc = "darwin-libSystem"
// Use macosx* instead of darwin, otherwise darwin/arm64 will refer to
@@ -399,6 +399,7 @@ func defaultTarget(options *Options) (*TargetSpec, error) {
)
spec.ExtraFiles = append(spec.ExtraFiles,
"src/internal/futex/futex_darwin.c",
"src/internal/task/task_threads.c",
"src/runtime/os_darwin.c",
"src/runtime/runtime_unix.c",
"src/runtime/signal.c")
+1 -1
View File
@@ -10,7 +10,7 @@ import (
// Version of TinyGo.
// Update this value before release of new version of software.
const version = "0.38.0"
const version = "0.39.0-dev"
// Return TinyGo version, either in the form 0.30.0 or as a development version
// (like 0.30.0-dev-abcd012).
+27 -30
View File
@@ -229,36 +229,33 @@ func needsSyscallPackage(buildTags []string) bool {
// means use the TinyGo version.
func pathsToOverride(goMinor int, needsSyscallPackage bool) map[string]bool {
paths := map[string]bool{
"": true,
"crypto/": true,
"crypto/rand/": false,
"crypto/tls/": false,
"crypto/x509/": true,
"crypto/x509/internal/": true,
"crypto/x509/internal/macos/": false,
"device/": false,
"examples/": false,
"internal/": true,
"internal/abi/": false,
"internal/binary/": false,
"internal/bytealg/": false,
"internal/cm/": false,
"internal/futex/": false,
"internal/fuzz/": false,
"internal/reflectlite/": false,
"internal/gclayout": false,
"internal/task/": false,
"internal/wasi/": false,
"machine/": false,
"net/": true,
"net/http/": false,
"os/": true,
"reflect/": false,
"runtime/": false,
"sync/": true,
"testing/": true,
"tinygo/": false,
"unique/": false,
"": true,
"crypto/": true,
"crypto/rand/": false,
"crypto/tls/": false,
"device/": false,
"examples/": false,
"internal/": true,
"internal/abi/": false,
"internal/binary/": false,
"internal/bytealg/": false,
"internal/cm/": false,
"internal/futex/": false,
"internal/fuzz/": false,
"internal/reflectlite/": false,
"internal/gclayout": false,
"internal/task/": false,
"internal/wasi/": false,
"machine/": false,
"net/": true,
"net/http/": false,
"os/": true,
"reflect/": false,
"runtime/": false,
"sync/": true,
"testing/": true,
"tinygo/": false,
"unique/": false,
}
if goMinor >= 19 {
+4
View File
@@ -424,10 +424,12 @@ func optionsFromOSARCH(osarch string, sema chan struct{}) compileopts.Options {
}
func runTest(name string, options compileopts.Options, t *testing.T, cmdArgs, environmentVars []string) {
t.Helper()
runTestWithConfig(name, t, options, cmdArgs, environmentVars)
}
func runTestWithConfig(name string, t *testing.T, options compileopts.Options, cmdArgs, environmentVars []string) {
t.Helper()
// Get the expected output for this test.
// Note: not using filepath.Join as it strips the path separator at the end
// of the path.
@@ -876,6 +878,7 @@ func TestWasmExit(t *testing.T) {
// Check whether the output of a test equals the expected output.
func checkOutput(t *testing.T, filename string, actual []byte) {
t.Helper()
expectedOutput, err := os.ReadFile(filename)
if err != nil {
t.Fatal("could not read output file:", err)
@@ -884,6 +887,7 @@ func checkOutput(t *testing.T, filename string, actual []byte) {
}
func checkOutputData(t *testing.T, expectedOutput, actual []byte) {
t.Helper()
expectedOutput = bytes.ReplaceAll(expectedOutput, []byte("\r\n"), []byte("\n"))
actual = bytes.ReplaceAll(actual, []byte("\r\n"), []byte("\n"))
-185
View File
@@ -1,185 +0,0 @@
package macos
import (
"errors"
"time"
)
// Exported symbols copied from Big Go, but stripped of functionality.
// Allows building of crypto/x509 on macOS.
const (
ErrSecCertificateExpired = -67818
ErrSecHostNameMismatch = -67602
ErrSecNotTrusted = -67843
)
var ErrNoTrustSettings = errors.New("no trust settings found")
var SecPolicyAppleSSL = StringToCFString("1.2.840.113635.100.1.3") // defined by POLICYMACRO
var SecPolicyOid = StringToCFString("SecPolicyOid")
var SecTrustSettingsPolicy = StringToCFString("kSecTrustSettingsPolicy")
var SecTrustSettingsPolicyString = StringToCFString("kSecTrustSettingsPolicyString")
var SecTrustSettingsResultKey = StringToCFString("kSecTrustSettingsResult")
func CFArrayAppendValue(array CFRef, val CFRef) {}
func CFArrayGetCount(array CFRef) int {
return 0
}
func CFDataGetBytePtr(data CFRef) uintptr {
return 0
}
func CFDataGetLength(data CFRef) int {
return 0
}
func CFDataToSlice(data CFRef) []byte {
return nil
}
func CFEqual(a, b CFRef) bool {
return false
}
func CFErrorGetCode(errRef CFRef) int {
return 0
}
func CFNumberGetValue(num CFRef) (int32, error) {
return 0, errors.New("not implemented")
}
func CFRelease(ref CFRef) {}
func CFStringToString(ref CFRef) string {
return ""
}
func ReleaseCFArray(array CFRef) {}
func SecCertificateCopyData(cert CFRef) ([]byte, error) {
return nil, errors.New("not implemented")
}
func SecTrustEvaluateWithError(trustObj CFRef) (int, error) {
return 0, errors.New("not implemented")
}
func SecTrustGetCertificateCount(trustObj CFRef) int {
return 0
}
func SecTrustGetResult(trustObj CFRef, result CFRef) (CFRef, CFRef, error) {
return 0, 0, errors.New("not implemented")
}
func SecTrustSetVerifyDate(trustObj CFRef, dateRef CFRef) error {
return errors.New("not implemented")
}
type CFRef uintptr
func BytesToCFData(b []byte) CFRef {
return 0
}
func CFArrayCreateMutable() CFRef {
return 0
}
func CFArrayGetValueAtIndex(array CFRef, index int) CFRef {
return 0
}
func CFDateCreate(seconds float64) CFRef {
return 0
}
func CFDictionaryGetValueIfPresent(dict CFRef, key CFString) (value CFRef, ok bool) {
return 0, false
}
func CFErrorCopyDescription(errRef CFRef) CFRef {
return 0
}
func CFStringCreateExternalRepresentation(strRef CFRef) (CFRef, error) {
return 0, errors.New("not implemented")
}
func SecCertificateCreateWithData(b []byte) (CFRef, error) {
return 0, errors.New("not implemented")
}
func SecPolicyCreateSSL(name string) (CFRef, error) {
return 0, errors.New("not implemented")
}
func SecTrustCreateWithCertificates(certs CFRef, policies CFRef) (CFRef, error) {
return 0, errors.New("not implemented")
}
func SecTrustEvaluate(trustObj CFRef) (CFRef, error) {
return 0, errors.New("not implemented")
}
func SecTrustGetCertificateAtIndex(trustObj CFRef, i int) (CFRef, error) {
return 0, errors.New("not implemented")
}
func SecTrustSettingsCopyCertificates(domain SecTrustSettingsDomain) (certArray CFRef, err error) {
return 0, errors.New("not implemented")
}
func SecTrustSettingsCopyTrustSettings(cert CFRef, domain SecTrustSettingsDomain) (trustSettings CFRef, err error) {
return 0, errors.New("not implemented")
}
func TimeToCFDateRef(t time.Time) CFRef {
return 0
}
type CFString CFRef
func StringToCFString(s string) CFString {
return 0
}
type OSStatus struct {
// Has unexported fields.
}
func (s OSStatus) Error() string
type SecTrustResultType int32
const (
SecTrustResultInvalid SecTrustResultType = iota
SecTrustResultProceed
SecTrustResultConfirm // deprecated
SecTrustResultDeny
SecTrustResultUnspecified
SecTrustResultRecoverableTrustFailure
SecTrustResultFatalTrustFailure
SecTrustResultOtherError
)
type SecTrustSettingsDomain int32
const (
SecTrustSettingsDomainUser SecTrustSettingsDomain = iota
SecTrustSettingsDomainAdmin
SecTrustSettingsDomainSystem
)
type SecTrustSettingsResult int32
const (
SecTrustSettingsResultInvalid SecTrustSettingsResult = iota
SecTrustSettingsResultTrustRoot
SecTrustSettingsResultTrustAsRoot
SecTrustSettingsResultDeny
SecTrustSettingsResultUnspecified
)
+15 -24
View File
@@ -5,29 +5,20 @@ import "unsafe"
// Internal constants for gc layout
// See runtime/gc_precise.go
var (
NoPtrs unsafe.Pointer
Pointer unsafe.Pointer
String unsafe.Pointer
Slice unsafe.Pointer
type Layout uintptr
const (
// 16-bit int => bits = 4
// 32-bit int => bits = 5
// 64-bit int => bits = 6
sizeBits = 4 + unsafe.Sizeof(uintptr(0))/4
sizeShift = sizeBits + 1
NoPtrs = Layout(uintptr(0b0<<sizeShift) | uintptr(0b1<<1) | uintptr(1))
Pointer = Layout(uintptr(0b1<<sizeShift) | uintptr(0b1<<1) | uintptr(1))
String = Layout(uintptr(0b01<<sizeShift) | uintptr(0b10<<1) | uintptr(1))
Slice = Layout(uintptr(0b001<<sizeShift) | uintptr(0b11<<1) | uintptr(1))
)
func init() {
var sizeBits uintptr
switch unsafe.Sizeof(uintptr(0)) {
case 8:
sizeBits = 6
case 4:
sizeBits = 5
case 2:
sizeBits = 4
}
var sizeShift = sizeBits + 1
NoPtrs = unsafe.Pointer(uintptr(0b0<<sizeShift) | uintptr(0b1<<1) | uintptr(1))
Pointer = unsafe.Pointer(uintptr(0b1<<sizeShift) | uintptr(0b1<<1) | uintptr(1))
String = unsafe.Pointer(uintptr(0b01<<sizeShift) | uintptr(0b10<<1) | uintptr(1))
Slice = unsafe.Pointer(uintptr(0b001<<sizeShift) | uintptr(0b11<<1) | uintptr(1))
}
func (l Layout) AsPtr() unsafe.Pointer { return unsafe.Pointer(l) }
+4 -4
View File
@@ -708,16 +708,16 @@ func (r *RawType) gcLayout() unsafe.Pointer {
kind := r.Kind()
if kind < String {
return gclayout.NoPtrs
return gclayout.NoPtrs.AsPtr()
}
switch kind {
case Pointer, UnsafePointer, Chan, Map:
return gclayout.Pointer
return gclayout.Pointer.AsPtr()
case String:
return gclayout.String
return gclayout.String.AsPtr()
case Slice:
return gclayout.Slice
return gclayout.Slice.AsPtr()
}
// Unknown (for now); let the conservative pointer scanning handle it
+11
View File
@@ -0,0 +1,11 @@
//go:build darwin
package task
import "unsafe"
// MacOS uses a pointer so unsafe.Pointer should be fine:
//
// typedef struct _opaque_pthread_t *__darwin_pthread_t;
// typedef __darwin_pthread_t pthread_t;
type threadID unsafe.Pointer
+32 -5
View File
@@ -2,16 +2,28 @@
#define _GNU_SOURCE
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
// BDWGC also uses SIGRTMIN+6 on Linux, which seems like a reasonable choice.
#ifdef __linux__
#include <semaphore.h>
// BDWGC also uses SIGRTMIN+6 on Linux, which seems like a reasonable choice.
#define taskPauseSignal (SIGRTMIN + 6)
#endif
#elif __APPLE__
#include <dispatch/dispatch.h>
// SIGIO is for interrupt-driven I/O.
// I don't think anybody should be using this nowadays, so I think we can
// repurpose it as a signal for GC.
// BDWGC uses a special way to pause/resume other threads on MacOS, which may be
// better but needs more work. Using signal keeps the code similar between Linux
// and MacOS.
#define taskPauseSignal SIGIO
#endif // __linux__, __APPLE__
// Pointer to the current task.Task structure.
// Ideally the entire task.Task structure would be a thread-local variable but
@@ -23,7 +35,11 @@ struct state_pass {
void *args;
void *task;
uintptr_t *stackTop;
#if __APPLE__
dispatch_semaphore_t startlock;
#else
sem_t startlock;
#endif
};
// Handle the GC pause in Go.
@@ -41,8 +57,7 @@ void tinygo_task_init(void *mainTask, pthread_t *thread, int *numCPU, void *cont
// Register the "GC pause" signal for the entire process.
// Using pthread_kill, we can still send the signal to a specific thread.
struct sigaction act = { 0 };
act.sa_flags = SA_SIGINFO;
act.sa_handler = &tinygo_task_gc_pause;
act.sa_handler = tinygo_task_gc_pause;
sigaction(taskPauseSignal, &act, NULL);
// Obtain the number of CPUs available on program start (for NumCPU).
@@ -69,7 +84,11 @@ static void* start_wrapper(void *arg) {
// Notify the caller that the thread has successfully started and
// initialized.
#if __APPLE__
dispatch_semaphore_signal(state->startlock);
#else
sem_post(&state->startlock);
#endif
// Run the goroutine function.
start(args);
@@ -93,11 +112,19 @@ int tinygo_task_start(uintptr_t fn, void *args, void *task, pthread_t *thread, u
.task = task,
.stackTop = stackTop,
};
#if __APPLE__
state.startlock = dispatch_semaphore_create(0);
#else
sem_init(&state.startlock, 0, 0);
#endif
int result = pthread_create(thread, NULL, &start_wrapper, &state);
// Wait until the thread has been created and read all state_pass variables.
#if __APPLE__
dispatch_semaphore_wait(state.startlock, DISPATCH_TIME_FOREVER);
#else
sem_wait(&state.startlock);
#endif
return result;
}
+1 -1
View File
@@ -220,7 +220,7 @@ func gcScanGlobals()
var stackScanLock PMutex
//export tinygo_task_gc_pause
func tingyo_task_gc_pause() {
func tingyo_task_gc_pause(sig int32) {
// Wait until we get the signal to start scanning the stack.
Current().state.gcSem.Wait()
+2 -2
View File
@@ -27,8 +27,8 @@ const (
PC1 = portC + 1
PC2 = portC + 2
PC3 = portC + 3
PC4 = portC + 4
PC5 = portC + 5
PC4 = portC + 4 // peripherals: I2C0 SDA
PC5 = portC + 5 // peripherals: I2C0 SCL
PC6 = portC + 6
PC7 = portC + 7
PD0 = portD + 0
+4 -4
View File
@@ -28,8 +28,8 @@ const (
PC1 = portC + 1
PC2 = portC + 2
PC3 = portC + 3
PC4 = portC + 4
PC5 = portC + 5
PC4 = portC + 4 // peripherals: I2C0 SDA
PC5 = portC + 5 // peripherals: I2C0 SCL
PC6 = portC + 6
PC7 = portC + 7
PD0 = portD + 0
@@ -40,8 +40,8 @@ const (
PD5 = portD + 5 // peripherals: Timer0 channel B
PD6 = portD + 6 // peripherals: Timer0 channel A
PD7 = portD + 7
PE0 = portE + 0
PE1 = portE + 1
PE0 = portE + 0 // peripherals: I2C1 SDA
PE1 = portE + 1 // peripherals: I2C1 SCL
PE2 = portE + 2
PE3 = portE + 3
PE4 = portE + 4
+24 -20
View File
@@ -7,32 +7,36 @@ func CPUFrequency() uint32 {
return 48000000
}
// Note that the below pins have a few I2C pins listed that according to the
// datasheet don't support I2C yet they are used in practice on boards from
// Adafruit and Arduino. See machine_atsamd21_simulator.go for details.
// Hardware pins
const (
PA00 Pin = 0 // peripherals: TCC2 channel 0
PA01 Pin = 1 // peripherals: TCC2 channel 1
PA00 Pin = 0 // peripherals: TCC2 channel 0, sercomI2CM1 SDA
PA01 Pin = 1 // peripherals: TCC2 channel 1, sercomI2CM1 SCL
PA02 Pin = 2
PA03 Pin = 3
PA04 Pin = 4 // peripherals: TCC0 channel 0
PA05 Pin = 5 // peripherals: TCC0 channel 1
PA06 Pin = 6 // peripherals: TCC1 channel 0
PA07 Pin = 7 // peripherals: TCC1 channel 1
PA08 Pin = 8 // peripherals: TCC0 channel 0, TCC1 channel 2
PA09 Pin = 9 // peripherals: TCC0 channel 1, TCC1 channel 3
PA08 Pin = 8 // peripherals: TCC0 channel 0, TCC1 channel 2, sercomI2CM0 SDA, sercomI2CM2 SDA
PA09 Pin = 9 // peripherals: TCC0 channel 1, TCC1 channel 3, sercomI2CM0 SCL, sercomI2CM2 SCL
PA10 Pin = 10 // peripherals: TCC1 channel 0, TCC0 channel 2
PA11 Pin = 11 // peripherals: TCC1 channel 1, TCC0 channel 3
PA12 Pin = 12 // peripherals: TCC2 channel 0, TCC0 channel 2
PA13 Pin = 13 // peripherals: TCC2 channel 1, TCC0 channel 3
PA12 Pin = 12 // peripherals: TCC2 channel 0, TCC0 channel 2, sercomI2CM2 SDA, sercomI2CM4 SDA
PA13 Pin = 13 // peripherals: TCC2 channel 1, TCC0 channel 3, sercomI2CM2 SCL, sercomI2CM4 SCL
PA14 Pin = 14 // peripherals: TCC0 channel 0
PA15 Pin = 15 // peripherals: TCC0 channel 1
PA16 Pin = 16 // peripherals: TCC2 channel 0, TCC0 channel 2
PA17 Pin = 17 // peripherals: TCC2 channel 1, TCC0 channel 3
PA16 Pin = 16 // peripherals: TCC2 channel 0, TCC0 channel 2, sercomI2CM1 SDA, sercomI2CM3 SDA
PA17 Pin = 17 // peripherals: TCC2 channel 1, TCC0 channel 3, sercomI2CM1 SCL, sercomI2CM3 SCL
PA18 Pin = 18 // peripherals: TCC0 channel 2
PA19 Pin = 19 // peripherals: TCC0 channel 3
PA20 Pin = 20 // peripherals: TCC0 channel 2
PA21 Pin = 21 // peripherals: TCC0 channel 3
PA22 Pin = 22 // peripherals: TCC0 channel 0
PA23 Pin = 23 // peripherals: TCC0 channel 1
PA22 Pin = 22 // peripherals: TCC0 channel 0, sercomI2CM3 SDA, sercomI2CM5 SDA
PA23 Pin = 23 // peripherals: TCC0 channel 1, sercomI2CM3 SCL, sercomI2CM5 SCL
PA24 Pin = 24 // peripherals: TCC1 channel 2
PA25 Pin = 25 // peripherals: TCC1 channel 3
PA26 Pin = 26
@@ -43,22 +47,22 @@ const (
PA31 Pin = 31 // peripherals: TCC1 channel 1
PB00 Pin = 32
PB01 Pin = 33
PB02 Pin = 34
PB03 Pin = 35
PB02 Pin = 34 // peripherals: sercomI2CM5 SDA
PB03 Pin = 35 // peripherals: sercomI2CM5 SCL
PB04 Pin = 36
PB05 Pin = 37
PB06 Pin = 38
PB07 Pin = 39
PB08 Pin = 40
PB09 Pin = 41
PB08 Pin = 40 // peripherals: sercomI2CM4 SDA
PB09 Pin = 41 // peripherals: sercomI2CM4 SCL
PB10 Pin = 42 // peripherals: TCC0 channel 0
PB11 Pin = 43 // peripherals: TCC0 channel 1
PB12 Pin = 44 // peripherals: TCC0 channel 2
PB13 Pin = 45 // peripherals: TCC0 channel 3
PB12 Pin = 44 // peripherals: TCC0 channel 2, sercomI2CM4 SDA
PB13 Pin = 45 // peripherals: TCC0 channel 3, sercomI2CM4 SCL
PB14 Pin = 46
PB15 Pin = 47
PB16 Pin = 48 // peripherals: TCC0 channel 0
PB17 Pin = 49 // peripherals: TCC0 channel 1
PB16 Pin = 48 // peripherals: TCC0 channel 0, sercomI2CM5 SDA
PB17 Pin = 49 // peripherals: TCC0 channel 1, sercomI2CM5 SCL
PB18 Pin = 50
PB19 Pin = 51
PB20 Pin = 52
@@ -71,6 +75,6 @@ const (
PB27 Pin = 59
PB28 Pin = 60
PB29 Pin = 61
PB30 Pin = 62 // peripherals: TCC0 channel 0, TCC1 channel 2
PB31 Pin = 63 // peripherals: TCC0 channel 1, TCC1 channel 3
PB30 Pin = 62 // peripherals: TCC0 channel 0, TCC1 channel 2, sercomI2CM5 SDA
PB31 Pin = 63 // peripherals: TCC0 channel 1, TCC1 channel 3, sercomI2CM5 SCL
)
+18 -19
View File
@@ -31,25 +31,24 @@ const (
GP27 = GPIO27
GP28 = GPIO28
GP29 = GPIO29
GP30 = GPIO30 // peripherals: PWM7 channel A
GP31 = GPIO31 // peripherals: PWM7 channel B
GP32 = GPIO32 // peripherals: PWM8 channel A
GP33 = GPIO33 // peripherals: PWM8 channel B
GP34 = GPIO34 // peripherals: PWM9 channel A
GP35 = GPIO35 // peripherals: PWM9 channel B
GP36 = GPIO36 // peripherals: PWM10 channel A
GP37 = GPIO37 // peripherals: PWM10 channel B
GP38 = GPIO38 // peripherals: PWM11 channel A
GP39 = GPIO39 // peripherals: PWM11 channel B
GP40 = GPIO40 // peripherals: PWM8 channel A
GP41 = GPIO41 // peripherals: PWM8 channel B
GP42 = GPIO42 // peripherals: PWM9 channel A
GP43 = GPIO43 // peripherals: PWM9 channel B
GP44 = GPIO44 // peripherals: PWM10 channel A
GP45 = GPIO45 // peripherals: PWM10 channel B
GP46 = GPIO46 // peripherals: PWM11 channel A
GP47 = GPIO47 // peripherals: PWM11 channel B
GP30 = GPIO30
GP31 = GPIO31
GP32 = GPIO32
GP33 = GPIO33
GP34 = GPIO34
GP35 = GPIO35
GP36 = GPIO36
GP37 = GPIO37
GP38 = GPIO38
GP39 = GPIO39
GP40 = GPIO40
GP41 = GPIO41
GP42 = GPIO42
GP43 = GPIO43
GP44 = GPIO44
GP45 = GPIO45
GP46 = GPIO46
GP47 = GPIO47
)
var DefaultUART = UART0
+18
View File
@@ -0,0 +1,18 @@
//go:build stm32l0x1 && !nucleol031k6
// This file is for the bare STM32L0x1 (not for any specific board that is based
// on the STM32L0x1).
package machine
const (
I2C0_SCL_PIN = NoPin
I2C0_SDA_PIN = NoPin
UART_TX_PIN = NoPin
UART_RX_PIN = NoPin
SPI0_SDI_PIN = NoPin
SPI0_SDO_PIN = NoPin
SPI0_SCK_PIN = NoPin
)
+93 -5
View File
@@ -279,7 +279,7 @@ var (
// #===========#==========#===============#=================-=========#
// | SPI1 | LPSPI4 | PLL2(132 MHz) | D12/D11/D13/D10 : 3/3/3/3 |
// | SPI2 | LPSPI3 | PLL2(132 MHz) | D1/D26/D27/D0 : 7/2/2/7 |
// | SPI3 | LPSPI1 | PLL2(132 MHz) | D34/D35/D37/D36 : 4/4/4/4 |
// | SPI3 | LPSPI1 | PLL2(132 MHz) | D42/D43/D45/D44 : 4/4/4/4 |
// #===========#==========#===============#=================-=========#
const (
SPI1_SDI_PIN = D12
@@ -292,10 +292,52 @@ const (
SPI2_SCK_PIN = D27
SPI2_CS_PIN = D0
SPI3_SDI_PIN = D34
SPI3_SDO_PIN = D35
SPI3_SCK_PIN = D37
SPI3_CS_PIN = D36
SPI3_SDI_PIN = D42
SPI3_SDO_PIN = D43
SPI3_SCK_PIN = D45
SPI3_CS_PIN = D44
)
var (
SPI0 = SPI1 // SPI0 is an alias of SPI1 (LPSPI4)
SPI1 = &SPI{
Bus: nxp.LPSPI4,
muxSDI: muxSelect{ // D12 (PB1 [B0_01])
mux: nxp.IOMUXC_LPSPI4_SDI_SELECT_INPUT_DAISY_GPIO_B0_01_ALT3,
sel: &nxp.IOMUXC.LPSPI4_SDI_SELECT_INPUT,
},
muxSDO: muxSelect{ // D11 (PB2 [B0_02])
mux: nxp.IOMUXC_LPSPI4_SDO_SELECT_INPUT_DAISY_GPIO_B0_02_ALT3,
sel: &nxp.IOMUXC.LPSPI4_SDO_SELECT_INPUT,
},
muxSCK: muxSelect{ // D13 (PB3 [B0_03])
mux: nxp.IOMUXC_LPSPI4_SCK_SELECT_INPUT_DAISY_GPIO_B0_03_ALT3,
sel: &nxp.IOMUXC.LPSPI4_SCK_SELECT_INPUT,
},
muxCS: muxSelect{ // D10 (PB0 [B0_00])
mux: nxp.IOMUXC_LPSPI4_PCS0_SELECT_INPUT_DAISY_GPIO_B0_00_ALT3,
sel: &nxp.IOMUXC.LPSPI4_PCS0_SELECT_INPUT,
},
}
SPI2 = &SPI{
Bus: nxp.LPSPI3,
muxSDI: muxSelect{ // D1 (PA2 [AD_B0_02])
mux: nxp.IOMUXC_LPSPI3_SDI_SELECT_INPUT_DAISY_GPIO_AD_B0_02_ALT7,
sel: &nxp.IOMUXC.LPSPI3_SDI_SELECT_INPUT,
},
muxSDO: muxSelect{ // D26 (PA30 [AD_B1_14])
mux: nxp.IOMUXC_LPSPI3_SDO_SELECT_INPUT_DAISY_GPIO_AD_B1_14_ALT2,
sel: &nxp.IOMUXC.LPSPI3_SDO_SELECT_INPUT,
},
muxSCK: muxSelect{ // D27 (PA31 [AD_B1_15])
mux: nxp.IOMUXC_LPSPI3_SCK_SELECT_INPUT_DAISY_GPIO_AD_B1_15,
sel: &nxp.IOMUXC.LPSPI3_SCK_SELECT_INPUT,
},
muxCS: muxSelect{ // D0 (PA3 [AD_B0_03])
mux: nxp.IOMUXC_LPSPI3_PCS0_SELECT_INPUT_DAISY_GPIO_AD_B0_03_ALT7,
sel: &nxp.IOMUXC.LPSPI3_PCS0_SELECT_INPUT,
},
}
)
// #====================================================#
@@ -317,3 +359,49 @@ const (
I2C3_SDA_PIN = D25
I2C3_SCL_PIN = D24
)
var (
I2C0 = I2C1 // I2C0 is an alias for I2C1 (LPI2C1)
I2C1 = &_I2C1
_I2C1 = I2C{
Bus: nxp.LPI2C1,
sda: I2C1_SDA_PIN, // D18 (PA17 [AD_B1_01])
scl: I2C1_SCL_PIN, // D19 (PA16 [AD_B1_00])
muxSDA: muxSelect{
mux: nxp.IOMUXC_LPI2C1_SDA_SELECT_INPUT_DAISY_GPIO_AD_B1_01_ALT3,
sel: &nxp.IOMUXC.LPI2C1_SDA_SELECT_INPUT,
},
muxSCL: muxSelect{
mux: nxp.IOMUXC_LPI2C1_SCL_SELECT_INPUT_DAISY_GPIO_AD_B1_00_ALT3,
sel: &nxp.IOMUXC.LPI2C1_SCL_SELECT_INPUT,
},
}
I2C2 = &_I2C2
_I2C2 = I2C{
Bus: nxp.LPI2C3,
sda: I2C2_SDA_PIN, // D17 (PA22 [AD_B1_06])
scl: I2C2_SCL_PIN, // D16 (PA23 [AD_B1_07])
muxSDA: muxSelect{
mux: nxp.IOMUXC_LPI2C3_SDA_SELECT_INPUT_DAISY_GPIO_AD_B1_06_ALT1,
sel: &nxp.IOMUXC.LPI2C3_SDA_SELECT_INPUT,
},
muxSCL: muxSelect{
mux: nxp.IOMUXC_LPI2C3_SCL_SELECT_INPUT_DAISY_GPIO_AD_B1_07_ALT1,
sel: &nxp.IOMUXC.LPI2C3_SCL_SELECT_INPUT,
},
}
I2C3 = &_I2C3
_I2C3 = I2C{
Bus: nxp.LPI2C4,
sda: I2C3_SDA_PIN, // D25 (PA13 [AD_B0_13])
scl: I2C3_SCL_PIN, // D24 (PA12 [AD_B0_12])
muxSDA: muxSelect{
mux: nxp.IOMUXC_LPI2C4_SDA_SELECT_INPUT_DAISY_GPIO_AD_B0_13_ALT0,
sel: &nxp.IOMUXC.LPI2C4_SDA_SELECT_INPUT,
},
muxSCL: muxSelect{
mux: nxp.IOMUXC_LPI2C4_SCL_SELECT_INPUT_DAISY_GPIO_AD_B0_12_ALT0,
sel: &nxp.IOMUXC.LPI2C4_SCL_SELECT_INPUT,
},
}
)
+14 -11
View File
@@ -26,17 +26,20 @@ const (
)
var (
errI2CWriteTimeout = errors.New("I2C timeout during write")
errI2CReadTimeout = errors.New("I2C timeout during read")
errI2CBusReadyTimeout = errors.New("I2C timeout on bus ready")
errI2CSignalStartTimeout = errors.New("I2C timeout on signal start")
errI2CSignalReadTimeout = errors.New("I2C timeout on signal read")
errI2CSignalStopTimeout = errors.New("I2C timeout on signal stop")
errI2CAckExpected = errors.New("I2C error: expected ACK not NACK")
errI2CBusError = errors.New("I2C bus error")
errI2COverflow = errors.New("I2C receive buffer overflow")
errI2COverread = errors.New("I2C transmit buffer overflow")
errI2CNotImplemented = errors.New("I2C operation not yet implemented")
errI2CWriteTimeout = errors.New("i2c: timeout during write")
errI2CReadTimeout = errors.New("i2c: timeout during read")
errI2CBusReadyTimeout = errors.New("i2c: timeout on bus ready")
errI2CSignalStartTimeout = errors.New("i2c: timeout on signal start")
errI2CSignalReadTimeout = errors.New("i2c: timeout on signal read")
errI2CSignalStopTimeout = errors.New("i2c: timeout on signal stop")
errI2CAckExpected = errors.New("i2c: error: expected ACK not NACK")
errI2CBusError = errors.New("i2c: bus error")
errI2COverflow = errors.New("i2c: receive buffer overflow")
errI2COverread = errors.New("i2c: transmit buffer overflow")
errI2CNotImplemented = errors.New("i2c: operation not yet implemented")
errI2CNoDevices = errors.New("i2c: bus has no devices") // simulator only
errI2CMultipleDevices = errors.New("i2c: bus has address conflict") // simulator only
errI2CWrongAddress = errors.New("i2c: bus has devices but none with this address") // simulator only
)
// I2CTargetEvent reflects events on the I2C bus
+2 -2
View File
@@ -49,8 +49,8 @@ const (
PC5 = portC + 5
PC6 = portC + 6
PC7 = portC + 7
PD0 = portD + 0
PD1 = portD + 1
PD0 = portD + 0 // peripherals: I2C0 SCL
PD1 = portD + 1 // peripherals: I2C0 SDA
PD2 = portD + 2
PD3 = portD + 3
PD7 = portD + 7
@@ -0,0 +1,5 @@
//go:build !baremetal && (arduino || arduino_nano)
package machine
var I2C0 = &I2C{Bus: 0, PinsSDA: []Pin{PC4}, PinsSCL: []Pin{PC5}}
+18
View File
@@ -43,3 +43,21 @@ var TCC2 = &timerType{
{PA01, PA13, PA17}, // channel 1
},
}
var (
// According to the datasheet, only some pins have I2C support. However it
// looks like many boards just use any SERCOM I2C instance, even if the
// datasheet says those don't support I2C. I guess they do work in practice,
// then.
// These are:
// * PA00/PA01 for the Adafruit Circuit Playground Express (I2C1, SERCOM1).
// * PB02/PB03 for the Adafruit Circuit Playground Express (I2C0, SERCOM5).
// * PB08/PB09 for the Arduino Nano 33 IoT (I2C0, SERCOM4).
// https://cdn.sparkfun.com/datasheets/Dev/Arduino/Boards/Atmel-42181-SAM-D21_Datasheet.pdf
sercomI2CM0 = &I2C{Bus: 0, PinsSDA: []Pin{PA08}, PinsSCL: []Pin{PA09}}
sercomI2CM1 = &I2C{Bus: 1, PinsSDA: []Pin{PA00, PA16}, PinsSCL: []Pin{PA01, PA17}}
sercomI2CM2 = &I2C{Bus: 2, PinsSDA: []Pin{PA08, PA12}, PinsSCL: []Pin{PA09, PA13}}
sercomI2CM3 = &I2C{Bus: 3, PinsSDA: []Pin{PA16, PA22}, PinsSCL: []Pin{PA17, PA23}}
sercomI2CM4 = &I2C{Bus: 4, PinsSDA: []Pin{PA12, PB08, PB12}, PinsSCL: []Pin{PA13, PB09, PB13}}
sercomI2CM5 = &I2C{Bus: 5, PinsSDA: []Pin{PA22, PB02, PB16, PB30}, PinsSCL: []Pin{PA23, PB03, PB17, PB31}}
)
+10 -10
View File
@@ -81,22 +81,22 @@ const (
PA05 Pin = 5
PA06 Pin = 6
PA07 Pin = 7
PA08 Pin = 8 // peripherals: TCC0 channel 0, TCC1 channel 4
PA09 Pin = 9 // peripherals: TCC0 channel 1, TCC1 channel 5
PA08 Pin = 8 // peripherals: TCC0 channel 0, TCC1 channel 4, sercomI2CM0 SDA, sercomI2CM2 SDA
PA09 Pin = 9 // peripherals: TCC0 channel 1, TCC1 channel 5, sercomI2CM0 SCL, sercomI2CM2 SCL
PA10 Pin = 10 // peripherals: TCC0 channel 2, TCC1 channel 6
PA11 Pin = 11 // peripherals: TCC0 channel 3, TCC1 channel 7
PA12 Pin = 12 // peripherals: TCC0 channel 6, TCC1 channel 2
PA13 Pin = 13 // peripherals: TCC0 channel 7, TCC1 channel 3
PA12 Pin = 12 // peripherals: TCC0 channel 6, TCC1 channel 2, sercomI2CM2 SDA, sercomI2CM4 SDA
PA13 Pin = 13 // peripherals: TCC0 channel 7, TCC1 channel 3, sercomI2CM2 SCL, sercomI2CM4 SCL
PA14 Pin = 14 // peripherals: TCC2 channel 0, TCC1 channel 2
PA15 Pin = 15 // peripherals: TCC2 channel 1, TCC1 channel 3
PA16 Pin = 16 // peripherals: TCC1 channel 0, TCC0 channel 4
PA17 Pin = 17 // peripherals: TCC1 channel 1, TCC0 channel 5
PA16 Pin = 16 // peripherals: TCC1 channel 0, TCC0 channel 4, sercomI2CM1 SDA, sercomI2CM3 SDA
PA17 Pin = 17 // peripherals: TCC1 channel 1, TCC0 channel 5, sercomI2CM1 SCL, sercomI2CM3 SCL
PA18 Pin = 18 // peripherals: TCC1 channel 2, TCC0 channel 6
PA19 Pin = 19 // peripherals: TCC1 channel 3, TCC0 channel 7
PA20 Pin = 20 // peripherals: TCC1 channel 4, TCC0 channel 0
PA21 Pin = 21 // peripherals: TCC1 channel 5, TCC0 channel 1
PA22 Pin = 22 // peripherals: TCC1 channel 6, TCC0 channel 2
PA23 Pin = 23 // peripherals: TCC1 channel 7, TCC0 channel 3
PA22 Pin = 22 // peripherals: TCC1 channel 6, TCC0 channel 2, sercomI2CM3 SDA, sercomI2CM5 SDA
PA23 Pin = 23 // peripherals: TCC1 channel 7, TCC0 channel 3, sercomI2CM3 SCL, sercomI2CM5 SCL
PA24 Pin = 24 // peripherals: TCC2 channel 2
PA25 Pin = 25 // peripherals: TCC2 channel 3
PA26 Pin = 26
@@ -177,8 +177,8 @@ const (
PD05 Pin = 101
PD06 Pin = 102
PD07 Pin = 103
PD08 Pin = 104 // peripherals: TCC0 channel 1
PD09 Pin = 105 // peripherals: TCC0 channel 2
PD08 Pin = 104 // peripherals: TCC0 channel 1, sercomI2CM6 SDA, sercomI2CM7 SDA
PD09 Pin = 105 // peripherals: TCC0 channel 2, sercomI2CM6 SCL, sercomI2CM7 SCL
PD10 Pin = 106 // peripherals: TCC0 channel 3
PD11 Pin = 107 // peripherals: TCC0 channel 4
PD12 Pin = 108 // peripherals: TCC0 channel 5
+5
View File
@@ -0,0 +1,5 @@
//go:build !baremetal && hifive1b
package machine
var I2C0 = &I2C{Bus: 0, PinsSDA: []Pin{P12}, PinsSCL: []Pin{P13}}
+35 -16
View File
@@ -4,6 +4,8 @@ package machine
import (
"crypto/rand"
"errors"
"slices"
)
// Dummy machine package that calls out to external functions.
@@ -227,7 +229,9 @@ func adcRead(pin Pin) uint16
// I2C is a generic implementation of the Inter-IC communication protocol.
type I2C struct {
Bus uint8
Bus uint8
PinsSCL []Pin
PinsSDA []Pin
}
// I2CConfig is used to store config info for I2C.
@@ -239,7 +243,21 @@ type I2CConfig struct {
// Configure is intended to setup the I2C interface.
func (i2c *I2C) Configure(config I2CConfig) error {
i2cConfigure(i2c.Bus, config.SCL, config.SDA)
if i2c.PinsSCL != nil {
matchSCL := slices.Index(i2c.PinsSCL, config.SCL) >= 0
matchSDA := slices.Index(i2c.PinsSDA, config.SDA) >= 0
if !matchSCL && !matchSDA {
return errors.New("i2c: SCL and SDA pins are incorrect for this I2C instance")
} else if !matchSCL {
return errors.New("i2c: SCL pin is incorrect for this I2C instance")
} else if !matchSDA {
return errors.New("i2c: SDA pin is incorrect for this I2C instance")
}
}
if config.Frequency == 0 {
config.Frequency = 100 * KHz
}
i2cConfigure(i2c.Bus, config.SCL, config.SDA, config.Frequency)
return nil
}
@@ -261,19 +279,29 @@ func (i2c *I2C) Tx(addr uint16, w, r []byte) error {
rptr = &r[0]
rlen = len(r)
}
i2cTransfer(i2c.Bus, wptr, wlen, rptr, rlen)
// TODO: do something with the returned error code.
return nil
errCode := i2cTransfer(i2c.Bus, addr, wptr, wlen, rptr, rlen)
switch errCode {
case 0:
return nil
case 1:
return errI2CNoDevices
case 2:
return errI2CMultipleDevices
case 3:
return errI2CWrongAddress
default:
return errI2CBusError // unknown error code
}
}
//export __tinygo_i2c_configure
func i2cConfigure(bus uint8, scl Pin, sda Pin)
func i2cConfigure(bus uint8, scl Pin, sda Pin, frequency uint32)
//export __tinygo_i2c_set_baud_rate
func i2cSetBaudRate(bus uint8, br uint32)
//export __tinygo_i2c_transfer
func i2cTransfer(bus uint8, w *byte, wlen int, r *byte, rlen int) int
func i2cTransfer(bus uint8, addr uint16, w *byte, wlen int, r *byte, rlen int) int
type UART struct {
Bus uint8
@@ -336,15 +364,6 @@ var (
sercomUSART4 = UART{4}
sercomUSART5 = UART{5}
sercomI2CM0 = &I2C{0}
sercomI2CM1 = &I2C{1}
sercomI2CM2 = &I2C{2}
sercomI2CM3 = &I2C{3}
sercomI2CM4 = &I2C{4}
sercomI2CM5 = &I2C{5}
sercomI2CM6 = &I2C{6}
sercomI2CM7 = &I2C{7}
sercomSPIM0 = &SPI{0}
sercomSPIM1 = &SPI{1}
sercomSPIM2 = &SPI{2}
@@ -10,5 +10,4 @@ var (
UART1 = hardwareUART1
SPI0 = &SPI{0}
SPI1 = &SPI{1}
I2C0 = &I2C{0}
)
+6
View File
@@ -0,0 +1,6 @@
//go:build !baremetal && (microbit || pca10031 || hw_651)
package machine
var I2C0 = &I2C{Bus: 0}
var I2C1 = &I2C{Bus: 1}
@@ -58,3 +58,6 @@ var PWM3 = &timerType{
nil, // channel 3
},
}
var I2C0 = &I2C{Bus: 0}
var I2C1 = &I2C{Bus: 1}
+12
View File
@@ -94,3 +94,15 @@ var PWM7 = &timerType{
{GPIO15}, // channel B (1)
},
}
var I2C0 = &I2C{
Bus: 0,
PinsSCL: []Pin{GPIO1, GPIO5, GPIO9, GPIO13, GPIO17, GPIO21},
PinsSDA: []Pin{GPIO0, GPIO4, GPIO8, GPIO12, GPIO16, GPIO20},
}
var I2C1 = &I2C{
Bus: 0,
PinsSCL: []Pin{GPIO3, GPIO7, GPIO11, GPIO15, GPIO19, GPIO27},
PinsSDA: []Pin{GPIO2, GPIO6, GPIO10, GPIO14, GPIO18, GPIO26},
}
+2
View File
@@ -150,6 +150,8 @@ func (p Pin) Configure(config PinConfig) {
case PinAnalog:
p.setFunc(fnNULL)
p.pulloff()
// Disable digital input.
p.padCtrl().ClearBits(rp.PADS_BANK0_GPIO0_IE)
case PinUART:
p.setFunc(fnUART)
case PinPWM:
+18 -18
View File
@@ -5,24 +5,24 @@ package machine
// RP2350B has additional pins.
const (
GPIO30 Pin = 30 // peripherals: PWM7 channel A
GPIO31 Pin = 31 // peripherals: PWM7 channel B
GPIO32 Pin = 32 // peripherals: PWM8 channel A
GPIO33 Pin = 33 // peripherals: PWM8 channel B
GPIO34 Pin = 34 // peripherals: PWM9 channel A
GPIO35 Pin = 35 // peripherals: PWM9 channel B
GPIO36 Pin = 36 // peripherals: PWM10 channel A
GPIO37 Pin = 37 // peripherals: PWM10 channel B
GPIO38 Pin = 38 // peripherals: PWM11 channel A
GPIO39 Pin = 39 // peripherals: PWM11 channel B
GPIO40 Pin = 40 // peripherals: PWM8 channel A
GPIO41 Pin = 41 // peripherals: PWM8 channel B
GPIO42 Pin = 42 // peripherals: PWM9 channel A
GPIO43 Pin = 43 // peripherals: PWM9 channel B
GPIO44 Pin = 44 // peripherals: PWM10 channel A
GPIO45 Pin = 45 // peripherals: PWM10 channel B
GPIO46 Pin = 46 // peripherals: PWM11 channel A
GPIO47 Pin = 47 // peripherals: PWM11 channel B
GPIO30 Pin = 30 // peripherals: PWM7 channel A, I2C1 SDA
GPIO31 Pin = 31 // peripherals: PWM7 channel B, I2C1 SCL
GPIO32 Pin = 32 // peripherals: PWM8 channel A, I2C0 SDA
GPIO33 Pin = 33 // peripherals: PWM8 channel B, I2C0 SCL
GPIO34 Pin = 34 // peripherals: PWM9 channel A, I2C1 SDA
GPIO35 Pin = 35 // peripherals: PWM9 channel B, I2C1 SCL
GPIO36 Pin = 36 // peripherals: PWM10 channel A, I2C0 SDA
GPIO37 Pin = 37 // peripherals: PWM10 channel B, I2C0 SCL
GPIO38 Pin = 38 // peripherals: PWM11 channel A, I2C1 SDA
GPIO39 Pin = 39 // peripherals: PWM11 channel B, I2C1 SCL
GPIO40 Pin = 40 // peripherals: PWM8 channel A, I2C0 SDA
GPIO41 Pin = 41 // peripherals: PWM8 channel B, I2C0 SCL
GPIO42 Pin = 42 // peripherals: PWM9 channel A, I2C1 SDA
GPIO43 Pin = 43 // peripherals: PWM9 channel B, I2C1 SCL
GPIO44 Pin = 44 // peripherals: PWM10 channel A, I2C0 SDA
GPIO45 Pin = 45 // peripherals: PWM10 channel B, I2C0 SCL
GPIO46 Pin = 46 // peripherals: PWM11 channel A, I2C1 SDA
GPIO47 Pin = 47 // peripherals: PWM11 channel B, I2C1 SCL
)
// Analog pins on 2350b.
+3 -2
View File
@@ -73,14 +73,15 @@ func (c ADCChannel) Configure(config ADCConfig) error {
func (c ADCChannel) getOnce() uint16 {
// Make it safe to sample multiple ADC channels in separate go routines.
adcLock.Lock()
rp.ADC.CS.ReplaceBits(uint32(c), 0b111, rp.ADC_CS_AINSEL_Pos)
rp.ADC.CS.ReplaceBits(uint32(c)<<rp.ADC_CS_AINSEL_Pos, rp.ADC_CS_AINSEL_Msk, 0)
rp.ADC.CS.SetBits(rp.ADC_CS_START_ONCE)
waitForReady()
v := rp.ADC.RESULT.Get()
adcLock.Unlock()
// rp2040 is a 12-bit ADC, scale raw reading to 16-bits.
return uint16(rp.ADC.RESULT.Get()) << 4
return uint16(v) << 4
}
// getVoltage does a one-shot sample and returns a millivolts reading.
+24 -24
View File
@@ -4,34 +4,34 @@ package machine
const (
// GPIO pins
GPIO0 Pin = 0 // peripherals: PWM0 channel A
GPIO1 Pin = 1 // peripherals: PWM0 channel B
GPIO2 Pin = 2 // peripherals: PWM1 channel A
GPIO3 Pin = 3 // peripherals: PWM1 channel B
GPIO4 Pin = 4 // peripherals: PWM2 channel A
GPIO5 Pin = 5 // peripherals: PWM2 channel B
GPIO6 Pin = 6 // peripherals: PWM3 channel A
GPIO7 Pin = 7 // peripherals: PWM3 channel B
GPIO8 Pin = 8 // peripherals: PWM4 channel A
GPIO9 Pin = 9 // peripherals: PWM4 channel B
GPIO10 Pin = 10 // peripherals: PWM5 channel A
GPIO11 Pin = 11 // peripherals: PWM5 channel B
GPIO12 Pin = 12 // peripherals: PWM6 channel A
GPIO13 Pin = 13 // peripherals: PWM6 channel B
GPIO14 Pin = 14 // peripherals: PWM7 channel A
GPIO15 Pin = 15 // peripherals: PWM7 channel B
GPIO16 Pin = 16 // peripherals: PWM0 channel A
GPIO17 Pin = 17 // peripherals: PWM0 channel B
GPIO18 Pin = 18 // peripherals: PWM1 channel A
GPIO19 Pin = 19 // peripherals: PWM1 channel B
GPIO20 Pin = 20 // peripherals: PWM2 channel A
GPIO21 Pin = 21 // peripherals: PWM2 channel B
GPIO0 Pin = 0 // peripherals: PWM0 channel A, I2C0 SDA
GPIO1 Pin = 1 // peripherals: PWM0 channel B, I2C0 SCL
GPIO2 Pin = 2 // peripherals: PWM1 channel A, I2C1 SDA
GPIO3 Pin = 3 // peripherals: PWM1 channel B, I2C1 SCL
GPIO4 Pin = 4 // peripherals: PWM2 channel A, I2C0 SDA
GPIO5 Pin = 5 // peripherals: PWM2 channel B, I2C0 SCL
GPIO6 Pin = 6 // peripherals: PWM3 channel A, I2C1 SDA
GPIO7 Pin = 7 // peripherals: PWM3 channel B, I2C1 SCL
GPIO8 Pin = 8 // peripherals: PWM4 channel A, I2C0 SDA
GPIO9 Pin = 9 // peripherals: PWM4 channel B, I2C0 SCL
GPIO10 Pin = 10 // peripherals: PWM5 channel A, I2C1 SDA
GPIO11 Pin = 11 // peripherals: PWM5 channel B, I2C1 SCL
GPIO12 Pin = 12 // peripherals: PWM6 channel A, I2C0 SDA
GPIO13 Pin = 13 // peripherals: PWM6 channel B, I2C0 SCL
GPIO14 Pin = 14 // peripherals: PWM7 channel A, I2C1 SDA
GPIO15 Pin = 15 // peripherals: PWM7 channel B, I2C1 SCL
GPIO16 Pin = 16 // peripherals: PWM0 channel A, I2C0 SDA
GPIO17 Pin = 17 // peripherals: PWM0 channel B, I2C0 SCL
GPIO18 Pin = 18 // peripherals: PWM1 channel A, I2C1 SDA
GPIO19 Pin = 19 // peripherals: PWM1 channel B, I2C1 SCL
GPIO20 Pin = 20 // peripherals: PWM2 channel A, I2C0 SDA
GPIO21 Pin = 21 // peripherals: PWM2 channel B, I2C0 SCL
GPIO22 Pin = 22 // peripherals: PWM3 channel A
GPIO23 Pin = 23 // peripherals: PWM3 channel B
GPIO24 Pin = 24 // peripherals: PWM4 channel A
GPIO25 Pin = 25 // peripherals: PWM4 channel B
GPIO26 Pin = 26 // peripherals: PWM5 channel A
GPIO27 Pin = 27 // peripherals: PWM5 channel B
GPIO26 Pin = 26 // peripherals: PWM5 channel A, I2C1 SDA
GPIO27 Pin = 27 // peripherals: PWM5 channel B, I2C1 SCL
GPIO28 Pin = 28 // peripherals: PWM6 channel A
GPIO29 Pin = 29 // peripherals: PWM6 channel B
)
+43
View File
@@ -209,6 +209,21 @@ const (
KeyF23 Keycode = 114 | 0xF000
KeyF24 Keycode = 115 | 0xF000
// International keys for Japanese and other language keyboards
KeyInternational1 Keycode = 0x87 | 0xF000 // JIS "\" and "_"
KeyInternational2 Keycode = 0x88 | 0xF000 // JIS Katakana/Hiragana
KeyInternational3 Keycode = 0x89 | 0xF000 // JIS "¥" and "|"
KeyInternational4 Keycode = 0x8A | 0xF000 // JIS Henkan
KeyInternational5 Keycode = 0x8B | 0xF000 // JIS Muhenkan
KeyInternational6 Keycode = 0x8C | 0xF000 // JIS Numpad ","
// Language keys for input method switching
KeyLanguage1 Keycode = 0x90 | 0xF000 // Hangul/English
KeyLanguage2 Keycode = 0x91 | 0xF000 // Hanja
KeyLanguage3 Keycode = 0x92 | 0xF000 // JIS Katakana
KeyLanguage4 Keycode = 0x93 | 0xF000 // JIS Hiragana
KeyLanguage5 Keycode = 0x94 | 0xF000 // JIS Zenkaku/Hankaku
KeyUpArrow Keycode = KeyUp
KeyDownArrow Keycode = KeyDown
KeyLeftArrow Keycode = KeyLeft
@@ -222,6 +237,34 @@ const (
KeyRightShift Keycode = KeyModifierRightShift
KeyRightAlt Keycode = KeyModifierRightAlt
KeyRightGUI Keycode = KeyModifierRightGUI
// QMK compatibility aliases for international keys
KeyInt1 Keycode = KeyInternational1
KeyInt2 Keycode = KeyInternational2
KeyInt3 Keycode = KeyInternational3
KeyInt4 Keycode = KeyInternational4
KeyInt5 Keycode = KeyInternational5
KeyInt6 Keycode = KeyInternational6
// QMK compatibility aliases for language keys
KeyLng1 Keycode = KeyLanguage1
KeyLng2 Keycode = KeyLanguage2
KeyLng3 Keycode = KeyLanguage3
KeyLng4 Keycode = KeyLanguage4
KeyLng5 Keycode = KeyLanguage5
// Common keyboard layout aliases
KeyRo Keycode = KeyInternational1 // Japanese "ろ"
KeyKatakanaHiragana Keycode = KeyInternational2 // Japanese Katakana/Hiragana
KeyYen Keycode = KeyInternational3 // Japanese "¥"
KeyHenkan Keycode = KeyInternational4 // Japanese Henkan
KeyMuhenkan Keycode = KeyInternational5 // Japanese Muhenkan
KeyKpJpComma Keycode = KeyInternational6 // Japanese Numpad ","
KeyHangeul Keycode = KeyLanguage1 // Korean Hangul/English
KeyHanja Keycode = KeyLanguage2 // Korean Hanja
KeyKatakana Keycode = KeyLanguage3 // Japanese Katakana
KeyHiragana Keycode = KeyLanguage4 // Japanese Hiragana
KeyZenkakuHankaku Keycode = KeyLanguage5 // Japanese Zenkaku/Hankaku
)
// Keycodes for layout US English (0x0904)
+1 -1
View File
@@ -89,7 +89,7 @@ func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer {
gcLock.Lock()
needsResumeWorld = false
var ptr unsafe.Pointer
if layout == gclayout.NoPtrs {
if layout == gclayout.NoPtrs.AsPtr() {
// This object is entirely pointer free, for example make([]int, ...).
// Make sure the GC knows this so it doesn't scan the object
// unnecessarily to improve performance.
+1 -1
View File
@@ -51,7 +51,7 @@ func sliceGrow(oldBuf unsafe.Pointer, oldLen, oldCap, newCap, elemSize uintptr)
var layout unsafe.Pointer
// less type info here; can only go off element size
if elemSize < unsafe.Sizeof(uintptr(0)) {
layout = gclayout.NoPtrs
layout = gclayout.NoPtrs.AsPtr()
}
buf := alloc(newCap*elemSize, layout)
+4 -4
View File
@@ -60,7 +60,7 @@ func stringConcat(x, y _string) _string {
return x
} else {
length := x.length + y.length
buf := alloc(length, gclayout.NoPtrs)
buf := alloc(length, gclayout.NoPtrs.AsPtr())
memcpy(buf, unsafe.Pointer(x.ptr), x.length)
memcpy(unsafe.Add(buf, x.length), unsafe.Pointer(y.ptr), y.length)
return _string{ptr: (*byte)(buf), length: length}
@@ -73,7 +73,7 @@ func stringFromBytes(x struct {
len uintptr
cap uintptr
}) _string {
buf := alloc(x.len, gclayout.NoPtrs)
buf := alloc(x.len, gclayout.NoPtrs.AsPtr())
memcpy(buf, unsafe.Pointer(x.ptr), x.len)
return _string{ptr: (*byte)(buf), length: x.len}
}
@@ -84,7 +84,7 @@ func stringToBytes(x _string) (slice struct {
len uintptr
cap uintptr
}) {
buf := alloc(x.length, gclayout.NoPtrs)
buf := alloc(x.length, gclayout.NoPtrs.AsPtr())
memcpy(buf, unsafe.Pointer(x.ptr), x.length)
slice.ptr = (*byte)(buf)
slice.len = x.length
@@ -101,7 +101,7 @@ func stringFromRunes(runeSlice []rune) (s _string) {
}
// Allocate memory for the string.
s.ptr = (*byte)(alloc(s.length, gclayout.NoPtrs))
s.ptr = (*byte)(alloc(s.length, gclayout.NoPtrs.AsPtr()))
// Encode runes to UTF-8 and store the resulting bytes in the string.
index := uintptr(0)
+10
View File
@@ -0,0 +1,10 @@
MEMORY
{
FLASH_TEXT (rx) : ORIGIN = 0x08000000, LENGTH = 32K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 8K
}
_stack_size = 2K;
INCLUDE "targets/arm.ld"
+18
View File
@@ -0,0 +1,18 @@
{
"inherits": [
"cortex-m0plus"
],
"build-tags": [
"stm32l031",
"stm32l0x1",
"stm32l0",
"stm32"
],
"linkerscript": "targets/stm32l031x6.ld",
"extra-files": [
"src/device/stm32/stm32l0x1.s"
],
"flash-method": "openocd",
"openocd-interface": "cmsis-dap",
"openocd-target": "stm32l0"
}
+4
View File
@@ -175,10 +175,13 @@ func testGoOnBuiltins() {
var once sync.Once
var waitChan = make(chan struct{})
func testGoOnInterface(f Itf) {
go f.Nowait()
time.Sleep(time.Millisecond)
go f.Wait()
<-waitChan
time.Sleep(time.Millisecond * 2)
println("done with 'go on interface'")
}
@@ -204,6 +207,7 @@ func (f Foo) Nowait() {
func (f Foo) Wait() {
println("called: Foo.Wait")
close(waitChan)
time.Sleep(time.Microsecond)
println(" ...waited")
}
+7
View File
@@ -36,6 +36,13 @@ func chromectx(t *testing.T) context.Context {
// see https://chromium.googlesource.com/chromium/src/+/main/docs/security/apparmor-userns-restrictions.md
opts := append(chromedp.DefaultExecAllocatorOptions[:],
chromedp.NoSandbox,
chromedp.Flag("disable-web-security", true),
chromedp.Flag("safebrowsing-disable-auto-update", true),
chromedp.IgnoreCertErrors,
chromedp.Flag("disable-sync", true),
chromedp.Flag("disable-default-apps", true),
chromedp.NoFirstRun,
chromedp.Headless,
)
allocCtx, cancel := chromedp.NewExecAllocator(context.Background(), opts...)