From cb6edeae8029a3c6d484445475e343a9286ba701 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Sun, 30 Jun 2024 20:27:05 +0200 Subject: [PATCH] WIP: support for the CH32V003 chip --- .gitignore | 2 + GNUmakefile | 8 ++- builder/builder_test.go | 1 + src/device/riscv/handleinterrupt.S | 5 ++ src/internal/task/task_stack_tinygoriscv.S | 5 ++ src/machine/board_nanoch32v003.go | 5 ++ src/machine/machine_ch32v003.go | 72 +++++++++++++++++++++ src/runtime/asm_riscv.S | 5 ++ src/runtime/runtime_ch32v003.go | 75 ++++++++++++++++++++++ targets/ch32v003.json | 17 +++++ targets/ch32v003.ld | 9 +++ targets/nanoch32v003.json | 4 ++ 12 files changed, 207 insertions(+), 1 deletion(-) create mode 100644 src/machine/board_nanoch32v003.go create mode 100644 src/machine/machine_ch32v003.go create mode 100644 src/runtime/runtime_ch32v003.go create mode 100644 targets/ch32v003.json create mode 100644 targets/ch32v003.ld create mode 100644 targets/nanoch32v003.json diff --git a/.gitignore b/.gitignore index 9d4f702f8..eb7759d91 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/GNUmakefile b/GNUmakefile index 2cc70df7f..483574136 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -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 diff --git a/builder/builder_test.go b/builder/builder_test.go index 3bb3e9841..303b1c324 100644 --- a/builder/builder_test.go +++ b/builder/builder_test.go @@ -27,6 +27,7 @@ func TestClangAttributes(t *testing.T) { "cortex-m33", "cortex-m4", "cortex-m7", + "ch32v003", "esp32c3", "fe310", "gameboy-advance", diff --git a/src/device/riscv/handleinterrupt.S b/src/device/riscv/handleinterrupt.S index c206c0159..849db203e 100644 --- a/src/device/riscv/handleinterrupt.S +++ b/src/device/riscv/handleinterrupt.S @@ -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 diff --git a/src/internal/task/task_stack_tinygoriscv.S b/src/internal/task/task_stack_tinygoriscv.S index 5f6127427..e6a20c9e8 100644 --- a/src/internal/task/task_stack_tinygoriscv.S +++ b/src/internal/task/task_stack_tinygoriscv.S @@ -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 diff --git a/src/machine/board_nanoch32v003.go b/src/machine/board_nanoch32v003.go new file mode 100644 index 000000000..d53c51a17 --- /dev/null +++ b/src/machine/board_nanoch32v003.go @@ -0,0 +1,5 @@ +//go:build nanoch32v003 + +package machine + +const LED = PD6 diff --git a/src/machine/machine_ch32v003.go b/src/machine/machine_ch32v003.go new file mode 100644 index 000000000..22249ca34 --- /dev/null +++ b/src/machine/machine_ch32v003.go @@ -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) + } +} diff --git a/src/runtime/asm_riscv.S b/src/runtime/asm_riscv.S index c028d6d53..04af20154 100644 --- a/src/runtime/asm_riscv.S +++ b/src/runtime/asm_riscv.S @@ -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 diff --git a/src/runtime/runtime_ch32v003.go b/src/runtime/runtime_ch32v003.go new file mode 100644 index 000000000..23e7ea8ae --- /dev/null +++ b/src/runtime/runtime_ch32v003.go @@ -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<