diff --git a/LICENSE b/LICENSE index cd7a96f..1f9a231 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2020-2022 TinyGo Authors. All rights reserved. +Copyright (c) TinyGo Authors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are diff --git a/Makefile b/Makefile index 594dfb3..8449859 100644 --- a/Makefile +++ b/Makefile @@ -58,13 +58,10 @@ test-circuitplay-express: build/testrunner # ./build/testrunner /dev/ttyACM0 115200 5 test-maixbit: build/testrunner - cd ./maixbit - tinygo flash -size short -target=maixbit -port=/dev/ttyUSB0 ./ -# tinygo flash -size short -target=maixbit -port=/dev/maixbit ./maixbit/ + cd ./maixbit && tinygo flash -size short -target=maixbit -port=/dev/ttyUSB0 . @sleep 2.0s @echo "Running tests..." - ../build/testrunner /dev/ttyUSB0 115200 2 -# ./build/testrunner /dev/maixbit 115200 2 + ./build/testrunner /dev/ttyUSB0 115200 2 test-itsybitsy-nrf52840: build/testrunner # tinygo flash -size short -target=itsybitsy-nrf52840 -port=/dev/itsybitsy_nrf52840 ./itsybitsy-nrf52840/ @@ -81,6 +78,12 @@ test-stm32f407disco: build/testrunner # ./build/testrunner /dev/hifive1b 115200 5 ./build/testrunner /dev/ttyUSB0 115200 3 +test-xiao-esp32c3: build/testrunner + cd ./xiao-esp32c3 && tinygo flash -size short -target=xiao-esp32c3 -port=/dev/ttyACM0 . + @sleep 5.0s + @echo "Running tests..." + ./build/testrunner /dev/ttyACM0 115200 2 + update-go: wget "https://dl.google.com/go/$(TARGET_GOVERSION).linux-amd64.tar.gz" -O /tmp/go.tar.gz sudo rm -rf /usr/local/go diff --git a/README.md b/README.md index bb30296..f11750d 100644 --- a/README.md +++ b/README.md @@ -7,15 +7,19 @@ TinyHCI is used to test the TinyGo (http://tinygo.org) `machine` package's hardw Hardware in the loop integration tests have been implemented for the following 10 boards: - Adafruit Circuit Playground Express (Microchip SAMD21x based on ARM Cortex-M0) -- Adafruit ItsyBitsy-M4 (Microchip SAMD51x based on ARM Cortex-M4) - Adafruit ItsyBitsy-NRF52840 (Nordic Semiconductor nRF52840 based on ARM Cortex-M4) - Arduino Nano33-IoT (Microchip SAMD21x based on ARM Cortex-M0) - Arduino Uno (Atmel ATmega328p based on AVR) -- bbc:microbit (Nordic Semiconductor nRF51 based on ARM Cortex-M0) - Raspberry Pi RP2040 Pico (Raspberry Pi Ltd 32-bit dual ARM Cortex-M0+) +- STMicro STM32F407 Discovery (STMicro STM32F407VG based on ARM Cortex-M4) +- Seeedstudio Xiao-ESP32C3 (32-bit core RISC-V microcontroller) + +The following boards are current inactive: + +- Adafruit ItsyBitsy-M4 (Microchip SAMD51x based on ARM Cortex-M4) +- bbc:microbit (Nordic Semiconductor nRF51 based on ARM Cortex-M0) - SiFive HiFive1 RevB (Freedom E310 based on RISC-V) - Sipeed MAix BiT (Kendryte K210 based on RISC-V) -- STMicro STM32F407 Discovery (STMicro STM32F407VG based on ARM Cortex-M4) ## How it works diff --git a/tools/docker/Dockerfile b/tools/docker/Dockerfile index 3d5bd86..ec24844 100644 --- a/tools/docker/Dockerfile +++ b/tools/docker/Dockerfile @@ -13,7 +13,9 @@ RUN git clone https://github.com/shumatech/BOSSA.git && \ RUN pip3 install git+https://github.com/kendryte/kflash.py.git --break-system-packages -ENV GO_RELEASE=1.25.4 +RUN pip3 install esptool --break-system-packages + +ENV GO_RELEASE=1.25.5 RUN wget https://dl.google.com/go/go${GO_RELEASE}.linux-amd64.tar.gz && \ tar xfv go${GO_RELEASE}.linux-amd64.tar.gz -C /usr/local && \ rm go${GO_RELEASE}.linux-amd64.tar.gz diff --git a/tools/server/boards.go b/tools/server/boards.go index 1766de1..85754b8 100644 --- a/tools/server/boards.go +++ b/tools/server/boards.go @@ -72,7 +72,7 @@ var ( displayname: "Sipeed MAix BiT", port: "maixbit00", baud: 115200, - resetpause: 5 * time.Second, + resetpause: 10 * time.Second, enabled: false, }, &Board{ @@ -99,6 +99,14 @@ var ( resetpause: 5 * time.Second, enabled: true, }, + &Board{ + target: "xiao-esp32c3", + displayname: "Seeed Studio XIAO ESP32C3", + port: "xiao_esp32c3", + baud: 115200, + resetpause: 10 * time.Second, + enabled: true, + }, } ) @@ -117,9 +125,15 @@ func (board *Board) flash(sha string) (string, error) { if err != nil { return err.Error(), err } + + realdev, err := os.Readlink("/dev/" + board.port) + if err != nil { + return err.Error(), err + } + buildtag := fmt.Sprintf("tinygohci:%s", sha[:7]) - device := fmt.Sprintf("--device=/dev/%s:/dev/%s:rwm", board.port, board.port) - port := fmt.Sprintf("-port=/dev/%s", board.port) + device := fmt.Sprintf("--device=/dev/%s:/dev/%s:rwm", realdev, realdev) + port := fmt.Sprintf("-port=/dev/%s", realdev) workdir := fmt.Sprintf("/src/%s", board.target) out, err := exec.Command("docker", "run", device, @@ -140,7 +154,11 @@ func (board *Board) flash(sha string) (string, error) { } func (board *Board) test() (string, error) { - port := fmt.Sprintf("/dev/%s", board.port) + realdev, err := os.Readlink("/dev/" + board.port) + if err != nil { + return err.Error(), err + } + port := fmt.Sprintf("/dev/%s", realdev) br := strconv.Itoa(board.baud) out, err := exec.Command("./build/testrunner", port, br, "5").CombinedOutput() diff --git a/tools/udev/99-named-devices.rules b/tools/udev/99-named-devices.rules index 77a70cd..09bf729 100644 --- a/tools/udev/99-named-devices.rules +++ b/tools/udev/99-named-devices.rules @@ -53,3 +53,6 @@ SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="374b", \ # STM32F407 Discovery UART SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", SYMLINK+="stm32f4disco" + +# Xiao ESP32-C3 +SUBSYSTEM=="tty", ATTRS{idVendor}=="303a", ATTRS{idProduct}=="1001", MODE:="0666", SYMLINK+="xiao_esp32c3" diff --git a/xiao-esp32c3/go.mod b/xiao-esp32c3/go.mod new file mode 100644 index 0000000..5719a2a --- /dev/null +++ b/xiao-esp32c3/go.mod @@ -0,0 +1,9 @@ +module xiao-esp32c3 + +go 1.22.1 + +toolchain go1.24.2 + +require tinygo.org/x/drivers v0.34.0 + +require github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect diff --git a/xiao-esp32c3/go.sum b/xiao-esp32c3/go.sum new file mode 100644 index 0000000..a1c68f7 --- /dev/null +++ b/xiao-esp32c3/go.sum @@ -0,0 +1,4 @@ +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= +tinygo.org/x/drivers v0.34.0 h1:lw8ePJeUSn9oICKBvQXHC9TIE+J00OfXfkGTrpXM9Iw= +tinygo.org/x/drivers v0.34.0/go.mod h1:ZdErNrApSABdVXjA1RejD67R8SNRI6RKVfYgQDZtKtk= diff --git a/xiao-esp32c3/main.go b/xiao-esp32c3/main.go new file mode 100644 index 0000000..758f72f --- /dev/null +++ b/xiao-esp32c3/main.go @@ -0,0 +1,199 @@ +package main + +// Integration tests for Xiao ESP32-C3 +// +// Wire up the pins, and run it while connected to the USB port. +// +// Digital read/write tests (GPIO): +// D0 <--> 3V3 +// D2 <--> D3 +// +// I2C tests: +// Xiao ESP32-C3 SCL (D5) <--> MPU6050 SCL +// Xiao ESP32-C3 SDA (D4) <--> MPU6050 SDA +// Xiao ESP32-C3 G <--> MPU6050 GND +// Xiao ESP32-C3 3V3 <--> MPU6050 VCC +// +// SPI tests: +// Xiao ESP32-C3 CDO - D10 <--> Xiao ESP32-C3 CDI - D9 +// +import ( + "machine" + + "time" + + "tinygo.org/x/drivers/mpu6050" +) + +var ( + // used by digital GPIO tests + readV = machine.D0 + readpin = machine.D2 + writepin = machine.D3 + + // used by i2c tests + accel *mpu6050.Device + powerpin = machine.D3 +) + +func main() { + waitForStart() + + digitalReadVoltageGPIO() + digitalWriteGPIO() + i2cConnection() + spiTxRx() + + endTests() +} + +// wait for keypress on serial port to start test suite. +func waitForStart() { + time.Sleep(5 * time.Second) + + println("=== TINYGO INTEGRATION TESTS ===") + println("Press 't' key to begin running tests...") + + for { + if machine.Serial.Buffered() > 0 { + data, _ := machine.Serial.ReadByte() + + if data != 't' { + time.Sleep(100 * time.Millisecond) + } + return + } + } +} + +func endTests() { + println("\n### Tests complete.") + + // tests done, now sleep waiting for baud reset to load new code + for { + time.Sleep(1 * time.Second) + } +} + +// digital read of a GPIO pin physically connected to V +func digitalReadVoltageGPIO() { + printtest("digitalReadVoltage (GPIO)") + + readV.Configure(machine.PinConfig{Mode: machine.PinInputPulldown}) + time.Sleep(100 * time.Millisecond) + + // should be on + if readV.Get() { + printtestresult("pass") + return + } + + printtestresult("fail") +} + +// digital write on/off of one GPIO pin as input physically connected to a different GPIO pin as output. +func digitalWriteGPIO() { + readpin.Configure(machine.PinConfig{Mode: machine.PinInputPulldown}) + writepin.Configure(machine.PinConfig{Mode: machine.PinOutput}) + time.Sleep(100 * time.Millisecond) + + printtest("digitalWriteOn (GPIO)") + writepin.High() + time.Sleep(100 * time.Millisecond) + + // should be on + if readpin.Get() { + printtestresult("pass") + } else { + printtestresult("fail") + } + + time.Sleep(100 * time.Millisecond) + + printtest("digitalWriteOff (GPIO)") + writepin.Low() + time.Sleep(100 * time.Millisecond) + + // should be off + if readpin.Get() { + printtestresult("fail") + return + } else { + printtestresult("pass") + } +} + +// checks to see if an attached MPU6050 accelerometer is connected. +func i2cConnection() { + machine.I2C0.Configure(machine.I2CConfig{}) + time.Sleep(100 * time.Millisecond) + + a := mpu6050.New(machine.I2C0) + accel = &a + + printtest("i2cConnection (MPU6050)") + + err := accel.Configure() + if err != nil { + printtestresult(err.Error()) + return + } + time.Sleep(400 * time.Millisecond) + + if !accel.Connected() { + printtestresult("fail") + return + } + + printtestresult("pass") +} + +// checks if it is possible to send/receive by spi +func spiTxRx() { + spi0 := machine.SPI2 + spi0.Configure(machine.SPIConfig{ + SCK: machine.SPI_SCK_PIN, + SDO: machine.SPI_SDO_PIN, + SDI: machine.SPI_SDI_PIN, + Frequency: 4000000, + }) + + from := make([]byte, 8) + for i := range from { + from[i] = byte(i) + } + to := make([]byte, len(from)) + + printtest("spiTx") + err := spi0.Tx(from, to) + if err != nil { + printtestresult("fail") + } else { + printtestresult("pass") + } + + printtest("spiRx") + for i := range from { + if from[i] != to[i] { + printtestresult("fail") + return + } + } + printtestresult("pass") +} + +func printtest(testname string) { + print("- " + testname + " = ") +} + +func printtestresult(result string) { + println("***" + result + "***") +} + +func printfailexpected(reason string) { + println(" expected:", reason) +} + +func printfailactual(val uint16) { + println(" actual:", val) +}