Compare commits

..

6 Commits

Author SHA1 Message Date
Ayke van Laethem cb6edeae80 WIP: support for the CH32V003 chip 2024-06-30 20:28:59 +02:00
deadprogram 4517a0c17b version: update to 0.33.0-dev
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-06-25 22:18:20 +02:00
Ayke van Laethem 6abaee4640 compiler: remove old atomics workaround for AVR
The bug should have been fixed in any LLVM version that we currently
support.
2024-06-25 09:27:31 +02:00
Ayke van Laethem 1270a50104 machine: use new internal/binary package
The encoding/binary package in Go 1.23 imports the slices package, which
results in circular import when imported from the machine package.
Therefore, encoding/binary cannot be used in the machine package.

This commit fixes that by introducing a new internal/binary package that
is just plain Go code without dependencies. It can be safely used
anywhere (including the runtime if needed).
2024-06-24 21:21:52 +02:00
Ayke van Laethem 868262f4a7 all: use latest version of x/tools
We previously picked a work-in-progress patch, but this is the proper
fix for this race condition. I think we should use that instead of
relying on the previous work-in-progress patch.
2024-06-23 19:11:06 +02:00
leongross d33ace7b59 remove unused registers for x86_64 linux syscalls
Signed-off-by: leongross <leon.gross@9elements.com>
2024-06-23 07:47:34 +02:00
29 changed files with 260 additions and 37 deletions
+2
View File
@@ -17,6 +17,8 @@ src/device/kendryte/*.go
src/device/kendryte/*.s
src/device/rp/*.go
src/device/rp/*.s
src/device/wch/*.go
src/device/wch/*.s
vendor
llvm-build
llvm-project
+7 -1
View File
@@ -185,7 +185,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-esp gen-device-nrf gen-device-sam gen-device-sifive gen-device-kendryte gen-device-nxp gen-device-rp
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-wch
ifneq ($(STM32), 0)
gen-device: gen-device-stm32
endif
@@ -237,6 +237,10 @@ gen-device-renesas: build/gen-device-svd
./build/gen-device-svd -source=https://github.com/tinygo-org/renesas-svd lib/renesas-svd/ src/device/renesas/
GO111MODULE=off $(GO) fmt ./src/device/renesas
gen-device-wch: build/gen-device-svd
./build/gen-device-svd -source=https://github.com/ch32-rs/ch32-rs/ lib/cmsis-svd/data/WCH-Community/ src/device/wch
GO111MODULE=off $(GO) fmt ./src/device/wch
# Get LLVM sources.
$(LLVM_PROJECTDIR)/llvm:
git clone -b tinygo_xtensa_release_18.1.2 --depth=1 https://github.com/tinygo-org/llvm-project $(LLVM_PROJECTDIR)
@@ -783,6 +787,8 @@ endif
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=maixbit examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=nanoch32v003 examples/blinky1
@$(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
+1
View File
@@ -27,6 +27,7 @@ func TestClangAttributes(t *testing.T) {
"cortex-m33",
"cortex-m4",
"cortex-m7",
"ch32v003",
"esp32c3",
"fe310",
"gameboy-advance",
-17
View File
@@ -1,9 +1,6 @@
package compiler
import (
"fmt"
"strings"
"tinygo.org/x/go-llvm"
)
@@ -15,20 +12,6 @@ func (b *builder) createAtomicOp(name string) llvm.Value {
case "AddInt32", "AddInt64", "AddUint32", "AddUint64", "AddUintptr":
ptr := b.getValue(b.fn.Params[0], getPos(b.fn))
val := b.getValue(b.fn.Params[1], getPos(b.fn))
if strings.HasPrefix(b.Triple, "avr") {
// AtomicRMW does not work on AVR as intended:
// - There are some register allocation issues (fixed by https://reviews.llvm.org/D97127 which is not yet in a usable LLVM release)
// - The result is the new value instead of the old value
vType := val.Type()
name := fmt.Sprintf("__sync_fetch_and_add_%d", vType.IntTypeWidth()/8)
fn := b.mod.NamedFunction(name)
if fn.IsNil() {
fn = llvm.AddFunction(b.mod, name, llvm.FunctionType(vType, []llvm.Type{ptr.Type(), vType}, false))
}
oldVal := b.createCall(fn.GlobalValueType(), fn, []llvm.Value{ptr, val}, "")
// Return the new value, not the original value returned.
return b.CreateAdd(oldVal, val, "")
}
oldVal := b.CreateAtomicRMW(llvm.AtomicRMWBinOpAdd, ptr, val, llvm.AtomicOrderingSequentiallyConsistent, true)
// Return the new value, not the original value returned by atomicrmw.
return b.CreateAdd(oldVal, val, "")
+6 -3
View File
@@ -33,18 +33,17 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) {
"{r10}",
"{r8}",
"{r9}",
"{r11}",
"{r12}",
"{r13}",
}[i]
llvmValue := b.getValue(arg, getPos(call))
args = append(args, llvmValue)
argTypes = append(argTypes, llvmValue.Type())
}
// rcx and r11 are clobbered by the syscall, so make sure they are not used
constraints += ",~{rcx},~{r11}"
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
target := llvm.InlineAsm(fnType, "syscall", constraints, true, false, llvm.InlineAsmDialectIntel, false)
return b.CreateCall(fnType, target, args, ""), nil
case b.GOARCH == "386" && b.GOOS == "linux":
// Sources:
// syscall(2) man page
@@ -71,6 +70,7 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) {
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
target := llvm.InlineAsm(fnType, "int 0x80", constraints, true, false, llvm.InlineAsmDialectIntel, false)
return b.CreateCall(fnType, target, args, ""), nil
case b.GOARCH == "arm" && b.GOOS == "linux":
// Implement the EABI system call convention for Linux.
// Source: syscall(2) man page.
@@ -103,6 +103,7 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) {
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
target := llvm.InlineAsm(fnType, "svc #0", constraints, true, false, 0, false)
return b.CreateCall(fnType, target, args, ""), nil
case b.GOARCH == "arm64" && b.GOOS == "linux":
// Source: syscall(2) man page.
args := []llvm.Value{}
@@ -135,6 +136,7 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) {
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
target := llvm.InlineAsm(fnType, "svc #0", constraints, true, false, 0, false)
return b.CreateCall(fnType, target, args, ""), nil
default:
return llvm.Value{}, b.makeError(call.Pos(), "unknown GOOS/GOARCH for syscall: "+b.GOOS+"/"+b.GOARCH)
}
@@ -217,6 +219,7 @@ func (b *builder) createSyscall(call *ssa.CallCommon) (llvm.Value, error) {
retval = b.CreateInsertValue(retval, syscallResult, 0, "")
retval = b.CreateInsertValue(retval, errResult, 2, "")
return retval, nil
default:
return llvm.Value{}, b.makeError(call.Pos(), "unknown GOOS/GOARCH for syscall: "+b.GOOS+"/"+b.GOARCH)
}
+1 -3
View File
@@ -19,7 +19,7 @@ require (
go.bug.st/serial v1.6.0
golang.org/x/net v0.26.0
golang.org/x/sys v0.21.0
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d
golang.org/x/tools v0.22.1-0.20240621165957-db513b091504
gopkg.in/yaml.v2 v2.4.0
tinygo.org/x/go-llvm v0.0.0-20240518103902-697964f2a9dc
)
@@ -45,5 +45,3 @@ require (
github.com/spf13/afero v1.11.0 // indirect
golang.org/x/text v0.16.0 // indirect
)
replace golang.org/x/tools => github.com/tinygo-org/tools v0.0.0-20240612102102-36af80766fc9
+2 -2
View File
@@ -80,8 +80,6 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/tinygo-org/tools v0.0.0-20240612102102-36af80766fc9 h1:t8VQNFa68kSA8ze7gi8kSxF22a7/vmr1OtOPLvgO3+8=
github.com/tinygo-org/tools v0.0.0-20240612102102-36af80766fc9/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
go.bug.st/serial v1.6.0 h1:mAbRGN4cKE2J5gMwsMHC2KQisdLRQssO9WSM+rbZJ8A=
go.bug.st/serial v1.6.0/go.mod h1:UABfsluHAiaNI+La2iESysd9Vetq7VRdpxvjx7CmmOE=
golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
@@ -99,6 +97,8 @@ golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/tools v0.22.1-0.20240621165957-db513b091504 h1:MMsD8mMfluf/578+3wrTn22pjI/Xkzm+gPW47SYfspY=
golang.org/x/tools v0.22.1-0.20240621165957-db513b091504/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
+1 -1
View File
@@ -9,7 +9,7 @@ import (
// Version of TinyGo.
// Update this value before release of new version of software.
const version = "0.32.0"
const version = "0.33.0-dev"
var (
// This variable is set at build time using -ldflags parameters.
+1
View File
@@ -236,6 +236,7 @@ func pathsToOverride(goMinor int, needsSyscallPackage bool) map[string]bool {
"device/": false,
"examples/": false,
"internal/": true,
"internal/binary/": false,
"internal/bytealg/": false,
"internal/fuzz/": false,
"internal/reflectlite/": false,
+5
View File
@@ -1,3 +1,6 @@
// We don't support RV32E at the moment.
#if !defined(__riscv_32e)
#ifdef __riscv_flen
#define NREG 48
#define LFREG flw
@@ -128,3 +131,5 @@ handleInterruptASM:
LREG ra, 0*REGSIZE(sp)
addi sp, sp, NREG*REGSIZE
mret
#endif
+32
View File
@@ -0,0 +1,32 @@
// Package binary is a lightweight replacement package for encoding/binary.
package binary
// This file contains small helper functions for working with binary data.
var LittleEndian = littleEndian{}
type littleEndian struct{}
// Encode data like encoding/binary.LittleEndian.Uint16.
func (littleEndian) Uint16(b []byte) uint16 {
return uint16(b[0]) | uint16(b[1])<<8
}
// Store data like binary.LittleEndian.PutUint16.
func (littleEndian) PutUint16(b []byte, v uint16) {
b[0] = byte(v)
b[1] = byte(v >> 8)
}
// Append data like binary.LittleEndian.AppendUint16.
func (littleEndian) AppendUint16(b []byte, v uint16) []byte {
return append(b,
byte(v),
byte(v>>8),
)
}
// Encode data like encoding/binary.LittleEndian.Uint32.
func (littleEndian) Uint32(b []byte) uint32 {
return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
}
@@ -1,5 +1,8 @@
//go:build tinygo
// We don't support RV32E at the moment.
#if !defined(__riscv_32e)
.section .text.tinygo_startTask
.global tinygo_startTask
.type tinygo_startTask, %function
@@ -69,3 +72,5 @@ tinygo_swapTask:
// Return into the task.
ret
#endif
+5
View File
@@ -0,0 +1,5 @@
//go:build nanoch32v003
package machine
const LED = PD6
+1 -1
View File
@@ -10,8 +10,8 @@ import (
"bytes"
"device/arm"
"device/sam"
"encoding/binary"
"errors"
"internal/binary"
"runtime/interrupt"
"unsafe"
)
+1 -1
View File
@@ -10,8 +10,8 @@ import (
"bytes"
"device/arm"
"device/sam"
"encoding/binary"
"errors"
"internal/binary"
"runtime/interrupt"
"unsafe"
)
+72
View File
@@ -0,0 +1,72 @@
//go:build ch32v003
package machine
import "device/wch"
const deviceName = wch.Device
const (
PA0 Pin = 0 + 0
PA1 Pin = 0 + 1
PA2 Pin = 0 + 2
PA3 Pin = 0 + 3
PA4 Pin = 0 + 4
PA5 Pin = 0 + 5
PA6 Pin = 0 + 6
PA7 Pin = 0 + 7
PC0 Pin = 16 + 0
PC1 Pin = 16 + 1
PC2 Pin = 16 + 2
PC3 Pin = 16 + 3
PC4 Pin = 16 + 4
PC5 Pin = 16 + 5
PC6 Pin = 16 + 6
PC7 Pin = 16 + 7
PD0 Pin = 24 + 0
PD1 Pin = 24 + 1
PD2 Pin = 24 + 2
PD3 Pin = 24 + 3
PD4 Pin = 24 + 4
PD5 Pin = 24 + 5
PD6 Pin = 24 + 6
PD7 Pin = 24 + 7
)
const (
PinInput PinMode = 0
PinOutput PinMode = 3
)
func (p Pin) getPortPin() (port *wch.GPIO_Type, pin uint32) {
portNum := uint32(p) >> 3
pin = uint32(p) & 0b111
switch portNum {
case 0:
port = wch.GPIOA
case 2:
port = wch.GPIOC
case 3:
port = wch.GPIOD
}
return
}
func (p Pin) Configure(config PinConfig) {
port, pin := p.getPortPin()
reg := port.CFGLR.Get()
reg &^= (0xf << (4 * pin))
reg |= 0b0000 << (4 * pin)
reg |= 0b11 << (4 * pin)
port.CFGLR.Set(reg)
}
// Set the pin to high or low.
func (p Pin) Set(high bool) {
port, pin := p.getPortPin()
if high {
port.BSHR.Set(1 << pin)
} else {
port.BCR.Set(1 << pin)
}
}
+1 -1
View File
@@ -5,7 +5,7 @@ package machine
import (
"bytes"
"device/nrf"
"encoding/binary"
"internal/binary"
"runtime/interrupt"
"unsafe"
)
+1 -1
View File
@@ -6,8 +6,8 @@ package machine
import (
"device/stm32"
"encoding/binary"
"errors"
"internal/binary"
"math/bits"
"runtime/interrupt"
"runtime/volatile"
+1 -1
View File
@@ -4,8 +4,8 @@ package machine
import (
"device/stm32"
"encoding/binary"
"errors"
"internal/binary"
"runtime/interrupt"
"runtime/volatile"
"unsafe"
+1 -1
View File
@@ -6,8 +6,8 @@ package machine
import (
"device/stm32"
"encoding/binary"
"errors"
"internal/binary"
"math/bits"
"runtime/interrupt"
"runtime/volatile"
+1 -1
View File
@@ -1,7 +1,7 @@
package descriptor
import (
"encoding/binary"
"internal/binary"
)
const (
+1 -1
View File
@@ -1,7 +1,7 @@
package descriptor
import (
"encoding/binary"
"internal/binary"
)
const (
+1 -1
View File
@@ -1,7 +1,7 @@
package descriptor
import (
"encoding/binary"
"internal/binary"
)
var endpointEP1IN = [endpointTypeLen]byte{
+1 -1
View File
@@ -2,8 +2,8 @@ package descriptor
import (
"bytes"
"encoding/binary"
"errors"
"internal/binary"
)
var configurationCDCHID = [configurationTypeLen]byte{
+5
View File
@@ -1,3 +1,6 @@
// We don't support RV32E at the moment.
#if !defined(__riscv_32e)
#if __riscv_xlen==64
#define REGSIZE 8
#define SREG sd
@@ -50,3 +53,5 @@ tinygo_longjmp:
lw sp, 0(a0) // jumpSP
lw a1, REGSIZE(a0) // jumpPC
jr a1
#endif
+75
View File
@@ -0,0 +1,75 @@
//go:build ch32v003
package runtime
import (
"device/wch"
"runtime/volatile"
)
//export main
func main() {
// Initialize main clock.
wch.RCC.CTLR.Set(wch.RCC_CTLR_HSION | wch.RCC_CTLR_PLLON)
wch.RCC.CFGR0.Set(0<<wch.RCC_CFGR0_HPRE_Pos | 0<<wch.RCC_CFGR0_PLLSRC_Pos)
wch.FLASH.ACTLR.Set(1 << wch.FLASH_ACTLR_LATENCY_Pos)
wch.RCC.INTR.Set(0x009F0000)
for (wch.RCC.CTLR.Get() & wch.RCC_CTLR_PLLRDY) == 0 {
}
wch.RCC.SetCFGR0_SW(0b10)
for (wch.RCC.CFGR0.Get() & wch.RCC_CFGR0_SWS_Msk) != 0x08 {
}
// Enable all GPIO pins (port A, C and D).
wch.RCC.APB2PCENR.SetBits(wch.RCC_APB2PCENR_IOPAEN | wch.RCC_APB2PCENR_IOPDEN | wch.RCC_APB2PCENR_IOPCEN)
run()
exit(0)
}
type timeUnit int64
var currentTicks timeUnit
func putchar(c byte) {
// TODO
}
func exit(code int) {
abort()
}
func ticks() timeUnit {
return currentTicks
}
// ticksToNanoseconds converts RTC ticks (at 32768Hz) to nanoseconds.
func ticksToNanoseconds(ticks timeUnit) int64 {
// The following calculation is actually the following, but with both sides
// reduced to reduce the risk of overflow:
// ticks * 1e9 / 32768
return int64(ticks) * 1953125 / 64
}
// nanosecondsToTicks converts nanoseconds to RTC ticks (running at 32768Hz).
func nanosecondsToTicks(ns int64) timeUnit {
// The following calculation is actually the following, but with both sides
// reduced to reduce the risk of overflow:
// ns * 32768 / 1e9
return timeUnit(ns * 64 / 1953125)
}
var dummyVolatile volatile.Register32
func sleepTicks(ticks timeUnit) {
// TODO: use a timer (using the low-speed clock)
loops := ticks * 70
for i := timeUnit(0); i < loops; i++ {
dummyVolatile.Get()
}
}
func abort() {
for {
}
}
+17
View File
@@ -0,0 +1,17 @@
{
"inherits": ["riscv32"],
"target-abi": "ilp32e",
"features": "+32bit,+c,+e,-a,-d,-experimental-zacas,-experimental-zcmop,-experimental-zfbfmin,-experimental-zicfilp,-experimental-zicfiss,-experimental-zimop,-experimental-ztso,-experimental-zvfbfmin,-experimental-zvfbfwma,-f,-h,-i,-m,-relax,-smaia,-smepmp,-ssaia,-svinval,-svnapot,-svpbmt,-v,-xcvalu,-xcvbi,-xcvbitmanip,-xcvelw,-xcvmac,-xcvmem,-xcvsimd,-xsfvcp,-xsfvfnrclipxfqf,-xsfvfwmaccqqq,-xsfvqmaccdod,-xsfvqmaccqoq,-xtheadba,-xtheadbb,-xtheadbs,-xtheadcmo,-xtheadcondmov,-xtheadfmemidx,-xtheadmac,-xtheadmemidx,-xtheadmempair,-xtheadsync,-xtheadvdot,-xventanacondops,-za128rs,-za64rs,-zawrs,-zba,-zbb,-zbc,-zbkb,-zbkc,-zbkx,-zbs,-zca,-zcb,-zcd,-zce,-zcf,-zcmp,-zcmt,-zdinx,-zfa,-zfh,-zfhmin,-zfinx,-zhinx,-zhinxmin,-zic64b,-zicbom,-zicbop,-zicboz,-ziccamoa,-ziccif,-zicclsm,-ziccrse,-zicntr,-zicond,-zicsr,-zifencei,-zihintntl,-zihintpause,-zihpm,-zk,-zkn,-zknd,-zkne,-zknh,-zkr,-zks,-zksed,-zksh,-zkt,-zmmul,-zvbb,-zvbc,-zve32f,-zve32x,-zve64d,-zve64f,-zve64x,-zvfh,-zvfhmin,-zvkb,-zvkg,-zvkn,-zvknc,-zvkned,-zvkng,-zvknha,-zvknhb,-zvks,-zvksc,-zvksed,-zvksg,-zvksh,-zvkt,-zvl1024b,-zvl128b,-zvl16384b,-zvl2048b,-zvl256b,-zvl32768b,-zvl32b,-zvl4096b,-zvl512b,-zvl64b,-zvl65536b,-zvl8192b",
"build-tags": ["ch32v003", "ch32v00xxx", "wch"],
"scheduler": "none",
"gc": "leaking",
"rtlib": "compiler-rt",
"libc": "picolibc",
"cflags": [
"-march=rv32ec"
],
"linkerscript": "targets/ch32v003.ld",
"extra-files": [
],
"flash-command": "probe-rs download --chip=CH32V003 {elf}"
}
+9
View File
@@ -0,0 +1,9 @@
MEMORY
{
FLASH_TEXT (rw) : ORIGIN = 0x00000000, LENGTH = 16K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 2K
}
_stack_size = 1K;
INCLUDE "targets/riscv.ld"
+4
View File
@@ -0,0 +1,4 @@
{
"inherits": ["ch32v003"],
"build-tags": ["nanoch32v003"]
}