From 6f6a42e460ee5cce969764b7cca15a3ca9cd3748 Mon Sep 17 00:00:00 2001 From: deadprogram Date: Mon, 25 Nov 2024 18:10:28 +0100 Subject: [PATCH 01/15] targets: initial implementation for Tillitis TKey device Signed-off-by: deadprogram --- GNUmakefile | 2 + src/device/tkey/crt0.S | 53 ++++++++++ src/device/tkey/tkey.go | 146 ++++++++++++++++++++++++++ src/machine/machine_tkey.go | 70 ++++++++++++ src/runtime/runtime_tkey.go | 60 +++++++++++ src/runtime/runtime_tkey_baremetal.go | 24 +++++ targets/tkey.json | 46 ++++++++ targets/tkey.ld | 78 ++++++++++++++ 8 files changed, 479 insertions(+) create mode 100644 src/device/tkey/crt0.S create mode 100644 src/device/tkey/tkey.go create mode 100644 src/machine/machine_tkey.go create mode 100644 src/runtime/runtime_tkey.go create mode 100644 src/runtime/runtime_tkey_baremetal.go create mode 100644 targets/tkey.json create mode 100644 targets/tkey.ld diff --git a/GNUmakefile b/GNUmakefile index 8daad25fb9..254f734940 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -853,6 +853,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=tkey 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/src/device/tkey/crt0.S b/src/device/tkey/crt0.S new file mode 100644 index 0000000000..94295ccba8 --- /dev/null +++ b/src/device/tkey/crt0.S @@ -0,0 +1,53 @@ +// SPDX-FileCopyrightText: 2022 Tillitis AB +// SPDX-License-Identifier: BSD-2-Clause + + .section ".text.init" + .global _start +_start: + li x1, 0 + li x2, 0 + li x3, 0 + li x4, 0 + li x5, 0 + li x6, 0 + li x7, 0 + li x8, 0 + li x9, 0 + li x10,0 + li x11,0 + li x12,0 + li x13,0 + li x14,0 + li x15,0 + li x16,0 + li x17,0 + li x18,0 + li x19,0 + li x20,0 + li x21,0 + li x22,0 + li x23,0 + li x24,0 + li x25,0 + li x26,0 + li x27,0 + li x28,0 + li x29,0 + li x30,0 + li x31,0 + + /* init stack */ + la sp, _stack_top + + /* zero-init bss section */ + la a0, _sbss + la a1, _ebss + bge a0, a1, end_init_bss + +loop_init_bss: + sw zero, 0(a0) + addi a0, a0, 4 + blt a0, a1, loop_init_bss + +end_init_bss: + call main diff --git a/src/device/tkey/tkey.go b/src/device/tkey/tkey.go new file mode 100644 index 0000000000..de46d7b030 --- /dev/null +++ b/src/device/tkey/tkey.go @@ -0,0 +1,146 @@ +//go:build tkey + +// Hand written file based on https://github.com/tillitis/tkey-libs/blob/main/include/tkey/tk1_mem.h + +package tkey + +import ( + "runtime/volatile" + "unsafe" +) + +// Peripherals +var ( + TRNG = (*TRNG_Type)(unsafe.Pointer(TK1_MMIO_TRNG_BASE)) + + TIMER = (*TIMER_Type)(unsafe.Pointer(TK1_MMIO_TIMER_BASE)) + + UDS = (*UDS_Type)(unsafe.Pointer(TK1_MMIO_UDS_BASE)) + + UART = (*UART_Type)(unsafe.Pointer(TK1_MMIO_UART_BASE)) + + TOUCH = (*TOUCH_Type)(unsafe.Pointer(TK1_MMIO_TOUCH_BASE)) + + TK1 = (*TK1_Type)(unsafe.Pointer(TK1_MMIO_TK1_BASE)) +) + +// Memory sections +const ( + TK1_ROM_BASE uintptr = 0x00000000 + + TK1_RAM_BASE uintptr = 0x40000000 + + TK1_MMIO_BASE uintptr = 0xc0000000 + + TK1_MMIO_TRNG_BASE uintptr = 0xc0000000 + + TK1_MMIO_TIMER_BASE uintptr = 0xc1000000 + + TK1_MMIO_UDS_BASE uintptr = 0xc2000000 + + TK1_MMIO_UART_BASE uintptr = 0xc3000000 + + TK1_MMIO_TOUCH_BASE uintptr = 0xc4000000 + + TK1_MMIO_FW_RAM_BASE uintptr = 0xd0000000 + + TK1_MMIO_TK1_BASE uintptr = 0xff000000 +) + +// Memory section sizes +const ( + TK1_RAM_SIZE uintptr = 0x20000 + + TK1_MMIO_SIZE uintptr = 0x3fffffff +) + +type TRNG_Type struct { + _ [36]byte + STATUS volatile.Register16 + _ [108]byte + ENTROPY volatile.Register16 +} + +type TIMER_Type struct { + _ [32]byte + CTRL volatile.Register16 + _ [2]byte + STATUS volatile.Register16 + _ [2]byte + PRESCALER volatile.Register32 + TIMER volatile.Register32 +} + +type UDS_Type struct { + DATA [8]volatile.Register16 +} + +type UART_Type struct { + _ [40]byte + BIT_RATE volatile.Register16 + _ [2]byte + DATA_BITS volatile.Register16 + _ [2]byte + STOP_BITS volatile.Register16 + _ [58]byte + RX_STATUS volatile.Register16 + _ [2]byte + RX_DATA volatile.Register16 + _ [2]byte + RX_BYTES volatile.Register16 + _ [16]byte + TX_STATUS volatile.Register16 + _ [2]byte + TX_DATA volatile.Register16 +} + +type TOUCH_Type struct { + _ [36]byte + STATUS volatile.Register16 +} + +type TK1_Type struct { + NAME0 [4]volatile.Register8 + NAME1 [4]volatile.Register8 + VERSION [4]volatile.Register8 + _ [16]byte + SWITCH_APP volatile.Register32 + _ [4]byte + LED volatile.Register32 + GPIO volatile.Register16 + APP_ADDR volatile.Register32 + APP_SIZE volatile.Register32 + BLAKE2S volatile.Register32 + _ [56]byte + CDI_FIRST [8]volatile.Register16 + _ [38]byte + UDI_FIRST [2]volatile.Register16 + _ [62]byte + RAM_ADDR_RAND volatile.Register16 + _ [2]byte + RAM_DATA_RAND volatile.Register16 + _ [126]byte + CPU_MON_CTRL volatile.Register16 + _ [2]byte + CPU_MON_FIRST volatile.Register32 + CPU_MON_LAST volatile.Register32 + _ [60]byte + SYSTEM_RESET volatile.Register16 + _ [66]byte + SPI_EN volatile.Register16 + _ [2]byte + SPI_XFER volatile.Register16 + _ [2]byte + SPI_DATA volatile.Register16 +} + +const ( + TK1_MMIO_TIMER_CTRL_START_BIT = 0 + TK1_MMIO_TIMER_CTRL_STOP_BIT = 1 + TK1_MMIO_TIMER_CTRL_START = 1 << TK1_MMIO_TIMER_CTRL_START_BIT + TK1_MMIO_TIMER_CTRL_STOP = 1 << TK1_MMIO_TIMER_CTRL_STOP_BIT + + TK1_MMIO_TK1_LED_R_BIT = 2 + TK1_MMIO_TK1_LED_G_BIT = 1 + TK1_MMIO_TK1_LED_B_BIT = 0 +) diff --git a/src/machine/machine_tkey.go b/src/machine/machine_tkey.go new file mode 100644 index 0000000000..d399ed43fe --- /dev/null +++ b/src/machine/machine_tkey.go @@ -0,0 +1,70 @@ +//go:build tkey + +package machine + +import ( + "device/tkey" +) + +const deviceName = "TKey" + +const ( + PinOutput PinMode = iota +) + +var ( + LED_BLUE = Pin(tkey.TK1_MMIO_TK1_LED_B_BIT) + LED_GREEN = Pin(tkey.TK1_MMIO_TK1_LED_G_BIT) + LED_RED = Pin(tkey.TK1_MMIO_TK1_LED_R_BIT) + + LED = LED_GREEN +) + +// No config needed for TKey, just to match the Pin interface. +func (p Pin) Configure(config PinConfig) { +} + +// Set GPIO pin to high or low. +func (p Pin) Set(high bool) { + switch p { + case LED_BLUE, LED_GREEN, LED_RED: + if high { + tkey.TK1.LED.SetBits(1 << uint(p)) + } else { + tkey.TK1.LED.ClearBits(1 << uint(p)) + } + } +} + +type UART struct { + Bus *tkey.UART_Type + Buffer *RingBuffer +} + +var ( + UART0 = &_UART0 + _UART0 = UART{Bus: tkey.UART, Buffer: NewRingBuffer()} +) + +func (uart *UART) Configure(config UARTConfig) { + if config.BaudRate == 0 { + config.BaudRate = 115200 + } + + uart.SetBaudRate(config.BaudRate) +} + +func (uart *UART) SetBaudRate(br uint32) { + uart.Bus.BIT_RATE.Set(uint16(18e6 / br)) +} + +func (uart *UART) writeByte(c byte) error { + for uart.Bus.TX_STATUS.Get() == 0 { + } + + uart.Bus.TX_DATA.Set(uint16(c)) + + return nil +} + +func (uart *UART) flush() {} diff --git a/src/runtime/runtime_tkey.go b/src/runtime/runtime_tkey.go new file mode 100644 index 0000000000..41eb9473e1 --- /dev/null +++ b/src/runtime/runtime_tkey.go @@ -0,0 +1,60 @@ +//go:build tkey + +// This file implements target-specific things for the TKey. + +package runtime + +import ( + "machine" + "runtime/volatile" +) + +type timeUnit int64 + +//export main +func main() { + preinit() + initPeripherals() + run() + exit(0) +} + +// initPeripherals configures peripherals the way the runtime expects them. +func initPeripherals() { + machine.InitSerial() +} + +func putchar(c byte) { + machine.Serial.WriteByte(c) +} + +func getchar() byte { + for machine.Serial.Buffered() == 0 { + Gosched() + } + v, _ := machine.Serial.ReadByte() + return v +} + +func buffered() int { + return machine.Serial.Buffered() +} + +var timestamp volatile.Register32 + +// ticks returns the current value of the timer in ticks. +func ticks() timeUnit { + return timeUnit(timestamp.Get()) +} + +// sleepTicks sleeps for at least the duration d. +func sleepTicks(d timeUnit) { + target := uint64(ticks() + d) + + for { + if uint64(ticks()) >= target { + break + } + timestamp.Set(timestamp.Get() + 1) + } +} diff --git a/src/runtime/runtime_tkey_baremetal.go b/src/runtime/runtime_tkey_baremetal.go new file mode 100644 index 0000000000..c232fcf619 --- /dev/null +++ b/src/runtime/runtime_tkey_baremetal.go @@ -0,0 +1,24 @@ +//go:build tkey && !qemu + +package runtime + +// ticksToNanoseconds converts ticks (at 18MHz) to nanoseconds. +func ticksToNanoseconds(ticks timeUnit) int64 { + return int64(ticks) * 1800 +} + +// nanosecondsToTicks converts nanoseconds to ticks (at 18MHz). +func nanosecondsToTicks(ns int64) timeUnit { + return timeUnit(ns / 1800) +} + +func exit(code int) { + abort() +} + +func abort() { + // lock up forever + for { + // TODO: something here? + } +} diff --git a/targets/tkey.json b/targets/tkey.json new file mode 100644 index 0000000000..814e103ce4 --- /dev/null +++ b/targets/tkey.json @@ -0,0 +1,46 @@ +{ + "goos": "linux", + "goarch": "arm", + "build-tags": [ + "tkey", + "tinygo.riscv32", + "tinygo.riscv", + "baremetal", + "linux", + "arm" + ], + "llvm-target": "riscv32-unknown-none", + "cpu": "generic-rv32", + "target-abi": "ilp32", + "features": "+c,+zmmul", + "cflags": [ + "-mcmodel=medany", + "-march=rv32iczmmul", + "-Werror", + "-mno-relax", + "-fno-exceptions", + "-fno-unwind-tables", + "-fno-asynchronous-unwind-tables", + "-ffunction-sections", + "-fdata-sections" + ], + "ldflags": [ + "-melf32lriscv", + "--gc-sections" + ], + "linkerscript": "targets/tkey.ld", + "gdb": [ + "gdb-multiarch" + ], + "scheduler": "none", + "default-stack-size": 2048, + "gc": "leaking", + "linker": "ld.lld", + "rtlib": "compiler-rt", + "libc": "picolibc", + "extra-files": [ + "src/runtime/asm_riscv.S", + "src/device/tkey/crt0.S" + ], + "flash-command": "tkey-runapp {bin}" +} diff --git a/targets/tkey.ld b/targets/tkey.ld new file mode 100644 index 0000000000..aae511e120 --- /dev/null +++ b/targets/tkey.ld @@ -0,0 +1,78 @@ +OUTPUT_ARCH( "riscv" ) +ENTRY(_start) + +MEMORY +{ + RAM (rwx) : ORIGIN = 0x40000000, LENGTH = 0x20000 /* 128 KB */ +} + +_stack_size = 2K; + +SECTIONS +{ + .text.init : + { + *(.text.init) + } >RAM + + .text : + { + . = ALIGN(4); + KEEP(*(.init)) + . = ALIGN(4); + *(.text) + *(.text.*) + *(.rodata) + *(.rodata.*) + . = ALIGN(4); + } >RAM + + /* Put the stack at the bottom of RAM, so that the application will + * crash on stack overflow instead of silently corrupting memory. + * See: http://blog.japaric.io/stack-overflow-protection/ */ + .stack (NOLOAD) : + { + . = ALIGN(16); + . += _stack_size; + _stack_top = .; + } >RAM + + /* Start address of .data, used by startup code. */ + _sidata = LOADADDR(.data); + + /* Globals with initial value */ + .data : + { + . = ALIGN(4); + /* see https://gnu-mcu-eclipse.github.io/arch/riscv/programmer/#the-gp-global-pointer-register */ + PROVIDE( __global_pointer$ = . + (4K / 2) ); + _sdata = .; /* used by startup code */ + *(.sdata) + *(.data .data.*) + . = ALIGN(4); + _edata = .; /* used by startup code */ + } >RAM + + /* Zero-initialized globals */ + .bss : + { + . = ALIGN(4); + _sbss = .; /* used by startup code */ + *(.sbss) + *(.bss .bss.*) + *(COMMON) + . = ALIGN(4); + _ebss = .; /* used by startup code */ + } >RAM + + /DISCARD/ : + { + *(.eh_frame) /* causes 'no memory region specified' error in lld */ + } +} + +/* For the memory allocator. */ +_heap_start = ALIGN(_ebss, 16); +_heap_end = ORIGIN(RAM) + LENGTH(RAM); +_globals_start = _sdata; +_globals_end = _ebss; From 4227e82b238b2ae9cdbbaa2106200e44440a7827 Mon Sep 17 00:00:00 2001 From: deadprogram Date: Wed, 27 Nov 2024 18:30:33 +0100 Subject: [PATCH 02/15] targets: add UART implementation for TKey Signed-off-by: deadprogram --- src/device/tkey/tkey.go | 23 +++++++--------------- src/machine/machine_tkey.go | 39 ++++++++++++++++++++++++------------- targets/tkey.json | 3 ++- 3 files changed, 35 insertions(+), 30 deletions(-) diff --git a/src/device/tkey/tkey.go b/src/device/tkey/tkey.go index de46d7b030..66e42738ed 100644 --- a/src/device/tkey/tkey.go +++ b/src/device/tkey/tkey.go @@ -76,22 +76,13 @@ type UDS_Type struct { } type UART_Type struct { - _ [40]byte - BIT_RATE volatile.Register16 - _ [2]byte - DATA_BITS volatile.Register16 - _ [2]byte - STOP_BITS volatile.Register16 - _ [58]byte - RX_STATUS volatile.Register16 - _ [2]byte - RX_DATA volatile.Register16 - _ [2]byte - RX_BYTES volatile.Register16 - _ [16]byte - TX_STATUS volatile.Register16 - _ [2]byte - TX_DATA volatile.Register16 + _ [128]byte + RX_STATUS volatile.Register32 + RX_DATA volatile.Register32 + RX_BYTES volatile.Register32 + _ [116]byte + TX_STATUS volatile.Register32 + TX_DATA volatile.Register32 } type TOUCH_Type struct { diff --git a/src/machine/machine_tkey.go b/src/machine/machine_tkey.go index d399ed43fe..c93fdecafa 100644 --- a/src/machine/machine_tkey.go +++ b/src/machine/machine_tkey.go @@ -37,34 +37,47 @@ func (p Pin) Set(high bool) { } type UART struct { - Bus *tkey.UART_Type - Buffer *RingBuffer + Bus *tkey.UART_Type } var ( - UART0 = &_UART0 - _UART0 = UART{Bus: tkey.UART, Buffer: NewRingBuffer()} + DefaultUART = UART0 + UART0 = &_UART0 + _UART0 = UART{Bus: tkey.UART} ) +// Thw TKey UART is fixed at 62500 baud, 8N1. func (uart *UART) Configure(config UARTConfig) { - if config.BaudRate == 0 { - config.BaudRate = 115200 - } - - uart.SetBaudRate(config.BaudRate) } func (uart *UART) SetBaudRate(br uint32) { - uart.Bus.BIT_RATE.Set(uint16(18e6 / br)) } -func (uart *UART) writeByte(c byte) error { +func (uart *UART) Write(data []byte) (n int, err error) { + for _, c := range data { + if err := uart.WriteByte(c); err != nil { + return n, err + } + } + return len(data), nil +} + +func (uart *UART) WriteByte(c byte) error { for uart.Bus.TX_STATUS.Get() == 0 { } - uart.Bus.TX_DATA.Set(uint16(c)) + uart.Bus.TX_DATA.Set(uint32(c)) return nil } -func (uart *UART) flush() {} +func (uart *UART) Buffered() int { + return int(uart.Bus.RX_BYTES.Get()) +} + +func (uart *UART) ReadByte() (byte, error) { + for uart.Bus.RX_STATUS.Get() == 0 { + } + + return byte(uart.Bus.RX_DATA.Get()), nil +} diff --git a/targets/tkey.json b/targets/tkey.json index 814e103ce4..c9d2af5cac 100644 --- a/targets/tkey.json +++ b/targets/tkey.json @@ -42,5 +42,6 @@ "src/runtime/asm_riscv.S", "src/device/tkey/crt0.S" ], - "flash-command": "tkey-runapp {bin}" + "flash-command": "tkey-runapp {bin}", + "serial": "uart" } From 49b75f00dd4fe75f581d1df626c0f3f7536f2161 Mon Sep 17 00:00:00 2001 From: deadprogram Date: Wed, 27 Nov 2024 20:21:23 +0100 Subject: [PATCH 03/15] targets: add Pin interface implementation for TKey touch sensor Signed-off-by: deadprogram --- src/device/tkey/tkey.go | 2 +- src/machine/machine_tkey.go | 39 ++++++++++++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/device/tkey/tkey.go b/src/device/tkey/tkey.go index 66e42738ed..92120cb670 100644 --- a/src/device/tkey/tkey.go +++ b/src/device/tkey/tkey.go @@ -87,7 +87,7 @@ type UART_Type struct { type TOUCH_Type struct { _ [36]byte - STATUS volatile.Register16 + STATUS volatile.Register32 } type TK1_Type struct { diff --git a/src/machine/machine_tkey.go b/src/machine/machine_tkey.go index c93fdecafa..bdfcaaddf1 100644 --- a/src/machine/machine_tkey.go +++ b/src/machine/machine_tkey.go @@ -8,20 +8,37 @@ import ( const deviceName = "TKey" +// GPIO pins modes are only here to match the Pin interface. +// The actual configuration is fixed in the hardware. const ( PinOutput PinMode = iota + PinInput + PinInputPullup + PinInputPulldown ) -var ( +const ( LED_BLUE = Pin(tkey.TK1_MMIO_TK1_LED_B_BIT) LED_GREEN = Pin(tkey.TK1_MMIO_TK1_LED_G_BIT) LED_RED = Pin(tkey.TK1_MMIO_TK1_LED_R_BIT) LED = LED_GREEN + + TKEY_TOUCH = Pin(3) // 3 is unused, but we need a value here to match the Pin interface. + BUTTON = TKEY_TOUCH ) +var buttonConfig PinConfig + // No config needed for TKey, just to match the Pin interface. func (p Pin) Configure(config PinConfig) { + switch p { + case BUTTON: + buttonConfig = config + + // Clear any pending touch events. + tkey.TOUCH.STATUS.Set(0) + } } // Set GPIO pin to high or low. @@ -36,6 +53,26 @@ func (p Pin) Set(high bool) { } } +func (p Pin) Get() bool { + switch p { + case BUTTON: + pushed := false + if tkey.TOUCH.STATUS.HasBits(1) { + tkey.TOUCH.STATUS.Set(0) + pushed = true + } + + switch buttonConfig.Mode { + case PinInputPullup: + return !pushed + case PinInput, PinInputPulldown: + return pushed + } + } + + return false +} + type UART struct { Bus *tkey.UART_Type } From 618cda3066effc248b2138607bbf70884a20097d Mon Sep 17 00:00:00 2001 From: deadprogram Date: Thu, 28 Nov 2024 12:58:30 +0100 Subject: [PATCH 04/15] targets: add RNG interface implementation for TKey Signed-off-by: deadprogram --- src/crypto/rand/rand_baremetal.go | 2 +- src/device/tkey/tkey.go | 6 +++--- src/machine/machine_tkey.go | 8 ++++++++ src/runtime/rand_hwrng.go | 2 +- src/runtime/rand_norng.go | 2 +- 5 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/crypto/rand/rand_baremetal.go b/src/crypto/rand/rand_baremetal.go index 15fc916ca6..30b2c3b230 100644 --- a/src/crypto/rand/rand_baremetal.go +++ b/src/crypto/rand/rand_baremetal.go @@ -1,4 +1,4 @@ -//go:build nrf || (stm32 && !(stm32f103 || stm32l0x1)) || (sam && atsamd51) || (sam && atsame5x) || esp32c3 +//go:build nrf || (stm32 && !(stm32f103 || stm32l0x1)) || (sam && atsamd51) || (sam && atsame5x) || esp32c3 || tkey // If you update the above build constraint, you'll probably also need to update // src/runtime/rand_hwrng.go. diff --git a/src/device/tkey/tkey.go b/src/device/tkey/tkey.go index 92120cb670..03afa5833d 100644 --- a/src/device/tkey/tkey.go +++ b/src/device/tkey/tkey.go @@ -56,9 +56,9 @@ const ( type TRNG_Type struct { _ [36]byte - STATUS volatile.Register16 - _ [108]byte - ENTROPY volatile.Register16 + STATUS volatile.Register32 + _ [88]byte + ENTROPY volatile.Register32 } type TIMER_Type struct { diff --git a/src/machine/machine_tkey.go b/src/machine/machine_tkey.go index bdfcaaddf1..926af68178 100644 --- a/src/machine/machine_tkey.go +++ b/src/machine/machine_tkey.go @@ -118,3 +118,11 @@ func (uart *UART) ReadByte() (byte, error) { return byte(uart.Bus.RX_DATA.Get()), nil } + +// GetRNG returns 32 bits of cryptographically secure random data +func GetRNG() (uint32, error) { + for tkey.TRNG.STATUS.Get() == 0 { + } + + return uint32(tkey.TRNG.ENTROPY.Get()), nil +} diff --git a/src/runtime/rand_hwrng.go b/src/runtime/rand_hwrng.go index 7154ffd79c..2c690b4490 100644 --- a/src/runtime/rand_hwrng.go +++ b/src/runtime/rand_hwrng.go @@ -1,4 +1,4 @@ -//go:build baremetal && (nrf || (stm32 && !(stm32f103 || stm32l0x1)) || (sam && atsamd51) || (sam && atsame5x) || esp32c3) +//go:build baremetal && (nrf || (stm32 && !(stm32f103 || stm32l0x1)) || (sam && atsamd51) || (sam && atsame5x) || esp32c3 || tkey) // If you update the above build constraint, you'll probably also need to update // src/crypto/rand/rand_baremetal.go. diff --git a/src/runtime/rand_norng.go b/src/runtime/rand_norng.go index e6045008e4..a86cdc5429 100644 --- a/src/runtime/rand_norng.go +++ b/src/runtime/rand_norng.go @@ -1,4 +1,4 @@ -//go:build baremetal && !(nrf || (stm32 && !(stm32f103 || stm32l0x1)) || (sam && atsamd51) || (sam && atsame5x) || esp32c3) +//go:build baremetal && !(nrf || (stm32 && !(stm32f103 || stm32l0x1)) || (sam && atsamd51) || (sam && atsame5x) || esp32c3 || tkey) package runtime From 6413d21ee56b63b3cf0aebbb83ed62e916b906ba Mon Sep 17 00:00:00 2001 From: deadprogram Date: Thu, 28 Nov 2024 15:06:39 +0100 Subject: [PATCH 05/15] targets: add helpful machine package functions to return identifiers such as name and version for TKey Signed-off-by: deadprogram --- src/device/tkey/tkey.go | 25 ++++++++-------- src/machine/machine_tkey.go | 58 +++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 13 deletions(-) diff --git a/src/device/tkey/tkey.go b/src/device/tkey/tkey.go index 03afa5833d..81f8f113e9 100644 --- a/src/device/tkey/tkey.go +++ b/src/device/tkey/tkey.go @@ -72,7 +72,8 @@ type TIMER_Type struct { } type UDS_Type struct { - DATA [8]volatile.Register16 + _ [64]byte + DATA [8]volatile.Register32 } type UART_Type struct { @@ -91,9 +92,9 @@ type TOUCH_Type struct { } type TK1_Type struct { - NAME0 [4]volatile.Register8 - NAME1 [4]volatile.Register8 - VERSION [4]volatile.Register8 + NAME0 volatile.Register32 + NAME1 volatile.Register32 + VERSION volatile.Register32 _ [16]byte SWITCH_APP volatile.Register32 _ [4]byte @@ -102,10 +103,10 @@ type TK1_Type struct { APP_ADDR volatile.Register32 APP_SIZE volatile.Register32 BLAKE2S volatile.Register32 - _ [56]byte - CDI_FIRST [8]volatile.Register16 - _ [38]byte - UDI_FIRST [2]volatile.Register16 + _ [72]byte + CDI_FIRST [8]volatile.Register32 + _ [32]byte + UDI_FIRST [2]volatile.Register32 _ [62]byte RAM_ADDR_RAND volatile.Register16 _ [2]byte @@ -118,11 +119,9 @@ type TK1_Type struct { _ [60]byte SYSTEM_RESET volatile.Register16 _ [66]byte - SPI_EN volatile.Register16 - _ [2]byte - SPI_XFER volatile.Register16 - _ [2]byte - SPI_DATA volatile.Register16 + SPI_EN volatile.Register32 + SPI_XFER volatile.Register32 + SPI_DATA volatile.Register32 } const ( diff --git a/src/machine/machine_tkey.go b/src/machine/machine_tkey.go index 926af68178..1461e97674 100644 --- a/src/machine/machine_tkey.go +++ b/src/machine/machine_tkey.go @@ -4,6 +4,7 @@ package machine import ( "device/tkey" + "strconv" ) const deviceName = "TKey" @@ -126,3 +127,60 @@ func GetRNG() (uint32, error) { return uint32(tkey.TRNG.ENTROPY.Get()), nil } + +// DesignName returns the FPGA design name. +func DesignName() (string, string) { + n0 := tkey.TK1.NAME0.Get() + name0 := string([]byte{byte(n0 >> 24), byte(n0 >> 16), byte(n0 >> 8), byte(n0)}) + n1 := tkey.TK1.NAME1.Get() + name1 := string([]byte{byte(n1 >> 24), byte(n1 >> 16), byte(n1 >> 8), byte(n1)}) + + return name0, name1 +} + +// DesignVersion returns the FPGA design version. +func DesignVersion() string { + version := tkey.TK1.VERSION.Get() + + return strconv.Itoa(int(version)) +} + +// CDI returns 8 words of Compound Device Identifier (CDI) generated and written by the firmware when the application is loaded. +func CDI() []byte { + cdi := make([]byte, 32) + for i := 0; i < 8; i++ { + c := tkey.TK1.CDI_FIRST[i].Get() + cdi[i*4] = byte(c >> 24) + cdi[i*4+1] = byte(c >> 16) + cdi[i*4+2] = byte(c >> 8) + cdi[i*4+3] = byte(c) + } + return cdi +} + +// UDI returns 2 words of Unique Device Identifier (UDI). Only available in firmware mode. +func UDI() []byte { + udi := make([]byte, 8) + for i := 0; i < 2; i++ { + c := tkey.TK1.UDI_FIRST[i].Get() + udi[i*4] = byte(c >> 24) + udi[i*4+1] = byte(c >> 16) + udi[i*4+2] = byte(c >> 8) + udi[i*4+3] = byte(c) + } + return udi +} + +// UDS returns 8 words of Unique Device Secret. Part of the FPGA design, changed when provisioning a TKey. +// Only available in firmware mode. UDS is only readable once per power cycle. +func UDS() []byte { + uds := make([]byte, 32) + for i := 0; i < 8; i++ { + c := tkey.UDS.DATA[i].Get() + uds[i*4] = byte(c >> 24) + uds[i*4+1] = byte(c >> 16) + uds[i*4+2] = byte(c >> 8) + uds[i*4+3] = byte(c) + } + return uds +} From 1070035a5ab44b36065d5d96b79c8329c6c720ac Mon Sep 17 00:00:00 2001 From: deadprogram Date: Thu, 28 Nov 2024 16:35:57 +0100 Subject: [PATCH 06/15] targets: use built-in timer for sleep timing on TKey Signed-off-by: deadprogram --- src/device/tkey/tkey.go | 6 ++---- src/runtime/runtime_tkey.go | 16 ++++++++++------ src/runtime/runtime_tkey_baremetal.go | 4 ++-- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/device/tkey/tkey.go b/src/device/tkey/tkey.go index 81f8f113e9..b4542eb4f0 100644 --- a/src/device/tkey/tkey.go +++ b/src/device/tkey/tkey.go @@ -63,10 +63,8 @@ type TRNG_Type struct { type TIMER_Type struct { _ [32]byte - CTRL volatile.Register16 - _ [2]byte - STATUS volatile.Register16 - _ [2]byte + CTRL volatile.Register32 + STATUS volatile.Register32 PRESCALER volatile.Register32 TIMER volatile.Register32 } diff --git a/src/runtime/runtime_tkey.go b/src/runtime/runtime_tkey.go index 41eb9473e1..5cc5c80801 100644 --- a/src/runtime/runtime_tkey.go +++ b/src/runtime/runtime_tkey.go @@ -5,6 +5,7 @@ package runtime import ( + "device/tkey" "machine" "runtime/volatile" ) @@ -21,6 +22,10 @@ func main() { // initPeripherals configures peripherals the way the runtime expects them. func initPeripherals() { + // prescaler value that results in 0.00001-second timer-ticks. + // given an 18 MHz processor, a millisecond is about 18,000 cycles. + tkey.TIMER.PRESCALER.Set(18_000_000 / 100000) + machine.InitSerial() } @@ -49,12 +54,11 @@ func ticks() timeUnit { // sleepTicks sleeps for at least the duration d. func sleepTicks(d timeUnit) { - target := uint64(ticks() + d) + target := uint32(ticks() + d) - for { - if uint64(ticks()) >= target { - break - } - timestamp.Set(timestamp.Get() + 1) + tkey.TIMER.TIMER.Set(uint32(d)) + tkey.TIMER.CTRL.SetBits(tkey.TK1_MMIO_TIMER_CTRL_START) + for tkey.TIMER.STATUS.Get() != 0 { } + timestamp.Set(target) } diff --git a/src/runtime/runtime_tkey_baremetal.go b/src/runtime/runtime_tkey_baremetal.go index c232fcf619..3d892a9dac 100644 --- a/src/runtime/runtime_tkey_baremetal.go +++ b/src/runtime/runtime_tkey_baremetal.go @@ -4,12 +4,12 @@ package runtime // ticksToNanoseconds converts ticks (at 18MHz) to nanoseconds. func ticksToNanoseconds(ticks timeUnit) int64 { - return int64(ticks) * 1800 + return int64(ticks) * 10000 } // nanosecondsToTicks converts nanoseconds to ticks (at 18MHz). func nanosecondsToTicks(ns int64) timeUnit { - return timeUnit(ns / 1800) + return timeUnit(ns / 10000) } func exit(code int) { From dd2fd4e92b35923ee78f6d6c3501be0c2b1baa03 Mon Sep 17 00:00:00 2001 From: deadprogram Date: Mon, 2 Dec 2024 09:21:52 +0100 Subject: [PATCH 07/15] targets: modify UART implementation for TKey to implement Serialer interface Signed-off-by: deadprogram --- src/machine/machine_tkey.go | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/machine/machine_tkey.go b/src/machine/machine_tkey.go index 1461e97674..6ca0502e45 100644 --- a/src/machine/machine_tkey.go +++ b/src/machine/machine_tkey.go @@ -85,12 +85,11 @@ var ( ) // Thw TKey UART is fixed at 62500 baud, 8N1. -func (uart *UART) Configure(config UARTConfig) { -} - -func (uart *UART) SetBaudRate(br uint32) { +func (uart *UART) Configure(config UARTConfig) error { + return nil } +// Write a slice of data bytes to the UART. func (uart *UART) Write(data []byte) (n int, err error) { for _, c := range data { if err := uart.WriteByte(c); err != nil { @@ -100,6 +99,7 @@ func (uart *UART) Write(data []byte) (n int, err error) { return len(data), nil } +// WriteByte writes a byte of data to the UART. func (uart *UART) WriteByte(c byte) error { for uart.Bus.TX_STATUS.Get() == 0 { } @@ -109,10 +109,12 @@ func (uart *UART) WriteByte(c byte) error { return nil } +// Buffered returns the number of bytes buffered in the UART. func (uart *UART) Buffered() int { return int(uart.Bus.RX_BYTES.Get()) } +// ReadByte reads a byte of data from the UART. func (uart *UART) ReadByte() (byte, error) { for uart.Bus.RX_STATUS.Get() == 0 { } @@ -120,6 +122,16 @@ func (uart *UART) ReadByte() (byte, error) { return byte(uart.Bus.RX_DATA.Get()), nil } +// DTR is not available on the TKey. +func (uart *UART) DTR() bool { + return false +} + +// RTS is not available on the TKey. +func (uart *UART) RTS() bool { + return false +} + // GetRNG returns 32 bits of cryptographically secure random data func GetRNG() (uint32, error) { for tkey.TRNG.STATUS.Get() == 0 { From 78f98d8e72cf74f65c29be15fef9dff509ec223e Mon Sep 17 00:00:00 2001 From: deadprogram Date: Tue, 3 Dec 2024 13:21:57 +0100 Subject: [PATCH 08/15] targets: implement BLAKE2s ROM function call for TKey device Signed-off-by: deadprogram --- src/machine/machine_tkey_rom.go | 59 +++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 src/machine/machine_tkey_rom.go diff --git a/src/machine/machine_tkey_rom.go b/src/machine/machine_tkey_rom.go new file mode 100644 index 0000000000..bc7162e047 --- /dev/null +++ b/src/machine/machine_tkey_rom.go @@ -0,0 +1,59 @@ +//go:build tkey + +package machine + +/* + #define TK1_MMIO_TK1_BLAKE2S 0xff000040 + + typedef unsigned char uint8_t; + typedef unsigned long uint32_t; + typedef unsigned long size_t; + + // blake2s state context + typedef struct { + uint8_t b[64]; // input buffer + uint32_t h[8]; // chained state + uint32_t t[2]; // total number of bytes + size_t c; // pointer for b[] + size_t outlen; // digest size + } blake2s_ctx; + + typedef int (*fw_blake2s_p)(void *out, unsigned long outlen, const void *key, + unsigned long keylen, const void *in, + unsigned long inlen, blake2s_ctx *ctx); + + int blake2s(void *out, unsigned long outlen, const void *key, unsigned long keylen, const void *in, unsigned long inlen) + { + fw_blake2s_p const fw_blake2s = + (fw_blake2s_p) * (volatile uint32_t *)TK1_MMIO_TK1_BLAKE2S; + blake2s_ctx ctx; + + return fw_blake2s(out, outlen, key, keylen, in, inlen, &ctx); + } +*/ +import "C" +import ( + "errors" + "unsafe" +) + +var ( + ErrBLAKE2sInvalid = errors.New("invalid params for call to BLAKE2s") + ErrBLAKE2sFailed = errors.New("call to BLAKE2s failed") +) + +func BLAKE2s(output []byte, key []byte, input []byte) error { + if len(output) == 0 || len(input) == 0 { + return ErrBLAKE2sInvalid + } + + op := unsafe.Pointer(&output[0]) + kp := unsafe.Pointer(&key[0]) + ip := unsafe.Pointer(&input[0]) + + if res := C.blake2s(op, C.size_t(len(output)), kp, C.size_t(len(key)), ip, C.size_t(len(input))); res != 0 { + return ErrBLAKE2sFailed + } + + return nil +} From 526116ae6d5689b6a37085db288b1b7fec98d189 Mon Sep 17 00:00:00 2001 From: deadprogram Date: Tue, 3 Dec 2024 14:31:31 +0100 Subject: [PATCH 09/15] targets: handle abort by triggering TKey device fault using illegal instruction to halt CPU Signed-off-by: deadprogram --- src/runtime/runtime_tkey_baremetal.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/runtime/runtime_tkey_baremetal.go b/src/runtime/runtime_tkey_baremetal.go index 3d892a9dac..1498e19c33 100644 --- a/src/runtime/runtime_tkey_baremetal.go +++ b/src/runtime/runtime_tkey_baremetal.go @@ -2,6 +2,8 @@ package runtime +import "device/riscv" + // ticksToNanoseconds converts ticks (at 18MHz) to nanoseconds. func ticksToNanoseconds(ticks timeUnit) int64 { return int64(ticks) * 10000 @@ -17,8 +19,6 @@ func exit(code int) { } func abort() { - // lock up forever - for { - // TODO: something here? - } + // Force illegal instruction to halt CPU + riscv.Asm("unimp") } From 544a6ef2a5a535ff75130f661390dab9e26bb915 Mon Sep 17 00:00:00 2001 From: deadprogram Date: Tue, 3 Dec 2024 18:55:02 +0100 Subject: [PATCH 10/15] targets: add Pin interface implementation for GPIO on TKey Signed-off-by: deadprogram --- src/device/tkey/tkey.go | 5 ++++ src/machine/machine_tkey.go | 49 +++++++++++++++++++++++++++++-------- 2 files changed, 44 insertions(+), 10 deletions(-) diff --git a/src/device/tkey/tkey.go b/src/device/tkey/tkey.go index b4542eb4f0..89a370414e 100644 --- a/src/device/tkey/tkey.go +++ b/src/device/tkey/tkey.go @@ -131,4 +131,9 @@ const ( TK1_MMIO_TK1_LED_R_BIT = 2 TK1_MMIO_TK1_LED_G_BIT = 1 TK1_MMIO_TK1_LED_B_BIT = 0 + + TK1_MMIO_TK1_GPIO1_BIT = 0 + TK1_MMIO_TK1_GPIO2_BIT = 1 + TK1_MMIO_TK1_GPIO3_BIT = 2 + TK1_MMIO_TK1_GPIO4_BIT = 3 ) diff --git a/src/machine/machine_tkey.go b/src/machine/machine_tkey.go index 6ca0502e45..ed7a57aabb 100644 --- a/src/machine/machine_tkey.go +++ b/src/machine/machine_tkey.go @@ -27,22 +27,31 @@ const ( TKEY_TOUCH = Pin(3) // 3 is unused, but we need a value here to match the Pin interface. BUTTON = TKEY_TOUCH + + GPIO1 = Pin(tkey.TK1_MMIO_TK1_GPIO1_BIT + 8) + GPIO2 = Pin(tkey.TK1_MMIO_TK1_GPIO2_BIT + 8) + GPIO3 = Pin(tkey.TK1_MMIO_TK1_GPIO3_BIT + 8) + GPIO4 = Pin(tkey.TK1_MMIO_TK1_GPIO4_BIT + 8) ) -var buttonConfig PinConfig +var touchConfig, gpio1Config, gpio2Config PinConfig // No config needed for TKey, just to match the Pin interface. func (p Pin) Configure(config PinConfig) { switch p { case BUTTON: - buttonConfig = config + touchConfig = config // Clear any pending touch events. tkey.TOUCH.STATUS.Set(0) + case GPIO1: + gpio1Config = config + case GPIO2: + gpio2Config = config } } -// Set GPIO pin to high or low. +// Set pin to high or low. func (p Pin) Set(high bool) { switch p { case LED_BLUE, LED_GREEN, LED_RED: @@ -51,26 +60,46 @@ func (p Pin) Set(high bool) { } else { tkey.TK1.LED.ClearBits(1 << uint(p)) } + case GPIO3, GPIO4: + if high { + tkey.TK1.GPIO.SetBits(1 << uint(p-8)) + } else { + tkey.TK1.GPIO.ClearBits(1 << uint(p-8)) + } } } +// Get returns the current value of a pin. func (p Pin) Get() bool { + pushed := false + mode := PinInput + switch p { case BUTTON: - pushed := false + mode = touchConfig.Mode if tkey.TOUCH.STATUS.HasBits(1) { tkey.TOUCH.STATUS.Set(0) pushed = true } - - switch buttonConfig.Mode { - case PinInputPullup: - return !pushed - case PinInput, PinInputPulldown: - return pushed + case GPIO1: + mode = gpio1Config.Mode + if tkey.TK1.GPIO.HasBits(1 << uint(p-8)) { + pushed = true + } + case GPIO2: + mode = gpio2Config.Mode + if tkey.TK1.GPIO.HasBits(1 << uint(p-8)) { + pushed = true } } + switch mode { + case PinInputPullup: + return !pushed + case PinInput, PinInputPulldown: + return pushed + } + return false } From f98715f84f5238624a4e7440bf80204a604fbf62 Mon Sep 17 00:00:00 2001 From: deadprogram Date: Wed, 11 Dec 2024 15:50:07 +0100 Subject: [PATCH 11/15] targets: simplify TKey implementation by inheriting from existing riscv32 target Signed-off-by: deadprogram --- src/device/tkey/crt0.S | 53 ------------------------------ targets/tkey.json | 35 ++------------------ targets/tkey.ld | 73 ++---------------------------------------- 3 files changed, 6 insertions(+), 155 deletions(-) delete mode 100644 src/device/tkey/crt0.S diff --git a/src/device/tkey/crt0.S b/src/device/tkey/crt0.S deleted file mode 100644 index 94295ccba8..0000000000 --- a/src/device/tkey/crt0.S +++ /dev/null @@ -1,53 +0,0 @@ -// SPDX-FileCopyrightText: 2022 Tillitis AB -// SPDX-License-Identifier: BSD-2-Clause - - .section ".text.init" - .global _start -_start: - li x1, 0 - li x2, 0 - li x3, 0 - li x4, 0 - li x5, 0 - li x6, 0 - li x7, 0 - li x8, 0 - li x9, 0 - li x10,0 - li x11,0 - li x12,0 - li x13,0 - li x14,0 - li x15,0 - li x16,0 - li x17,0 - li x18,0 - li x19,0 - li x20,0 - li x21,0 - li x22,0 - li x23,0 - li x24,0 - li x25,0 - li x26,0 - li x27,0 - li x28,0 - li x29,0 - li x30,0 - li x31,0 - - /* init stack */ - la sp, _stack_top - - /* zero-init bss section */ - la a0, _sbss - la a1, _ebss - bge a0, a1, end_init_bss - -loop_init_bss: - sw zero, 0(a0) - addi a0, a0, 4 - blt a0, a1, loop_init_bss - -end_init_bss: - call main diff --git a/targets/tkey.json b/targets/tkey.json index c9d2af5cac..aac6b80b46 100644 --- a/targets/tkey.json +++ b/targets/tkey.json @@ -1,47 +1,18 @@ { - "goos": "linux", - "goarch": "arm", - "build-tags": [ - "tkey", - "tinygo.riscv32", - "tinygo.riscv", - "baremetal", - "linux", - "arm" - ], - "llvm-target": "riscv32-unknown-none", - "cpu": "generic-rv32", - "target-abi": "ilp32", + "inherits": ["riscv32"], + "build-tags": ["tkey"], "features": "+c,+zmmul", "cflags": [ "-mcmodel=medany", - "-march=rv32iczmmul", - "-Werror", - "-mno-relax", - "-fno-exceptions", - "-fno-unwind-tables", - "-fno-asynchronous-unwind-tables", - "-ffunction-sections", - "-fdata-sections" - ], - "ldflags": [ - "-melf32lriscv", - "--gc-sections" + "-march=rv32iczmmul" ], "linkerscript": "targets/tkey.ld", - "gdb": [ - "gdb-multiarch" - ], "scheduler": "none", "default-stack-size": 2048, "gc": "leaking", "linker": "ld.lld", "rtlib": "compiler-rt", "libc": "picolibc", - "extra-files": [ - "src/runtime/asm_riscv.S", - "src/device/tkey/crt0.S" - ], "flash-command": "tkey-runapp {bin}", "serial": "uart" } diff --git a/targets/tkey.ld b/targets/tkey.ld index aae511e120..09becf4036 100644 --- a/targets/tkey.ld +++ b/targets/tkey.ld @@ -1,78 +1,11 @@ -OUTPUT_ARCH( "riscv" ) -ENTRY(_start) MEMORY { RAM (rwx) : ORIGIN = 0x40000000, LENGTH = 0x20000 /* 128 KB */ } -_stack_size = 2K; - -SECTIONS -{ - .text.init : - { - *(.text.init) - } >RAM - - .text : - { - . = ALIGN(4); - KEEP(*(.init)) - . = ALIGN(4); - *(.text) - *(.text.*) - *(.rodata) - *(.rodata.*) - . = ALIGN(4); - } >RAM - - /* Put the stack at the bottom of RAM, so that the application will - * crash on stack overflow instead of silently corrupting memory. - * See: http://blog.japaric.io/stack-overflow-protection/ */ - .stack (NOLOAD) : - { - . = ALIGN(16); - . += _stack_size; - _stack_top = .; - } >RAM +REGION_ALIAS("FLASH_TEXT", RAM); - /* Start address of .data, used by startup code. */ - _sidata = LOADADDR(.data); - - /* Globals with initial value */ - .data : - { - . = ALIGN(4); - /* see https://gnu-mcu-eclipse.github.io/arch/riscv/programmer/#the-gp-global-pointer-register */ - PROVIDE( __global_pointer$ = . + (4K / 2) ); - _sdata = .; /* used by startup code */ - *(.sdata) - *(.data .data.*) - . = ALIGN(4); - _edata = .; /* used by startup code */ - } >RAM - - /* Zero-initialized globals */ - .bss : - { - . = ALIGN(4); - _sbss = .; /* used by startup code */ - *(.sbss) - *(.bss .bss.*) - *(COMMON) - . = ALIGN(4); - _ebss = .; /* used by startup code */ - } >RAM - - /DISCARD/ : - { - *(.eh_frame) /* causes 'no memory region specified' error in lld */ - } -} +_stack_size = 2K; -/* For the memory allocator. */ -_heap_start = ALIGN(_ebss, 16); -_heap_end = ORIGIN(RAM) + LENGTH(RAM); -_globals_start = _sdata; -_globals_end = _ebss; +INCLUDE "targets/riscv.ld" From f25093796f44d153c9c18f1373e12be7c7ddb4c4 Mon Sep 17 00:00:00 2001 From: deadprogram Date: Wed, 11 Dec 2024 15:57:37 +0100 Subject: [PATCH 12/15] machine/tkey: return error for trying to configure invalid baudrates on UART Signed-off-by: deadprogram --- src/machine/machine_tkey.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/machine/machine_tkey.go b/src/machine/machine_tkey.go index ed7a57aabb..7a7850385b 100644 --- a/src/machine/machine_tkey.go +++ b/src/machine/machine_tkey.go @@ -4,6 +4,7 @@ package machine import ( "device/tkey" + "errors" "strconv" ) @@ -113,8 +114,12 @@ var ( _UART0 = UART{Bus: tkey.UART} ) -// Thw TKey UART is fixed at 62500 baud, 8N1. +// The TKey UART is fixed at 62500 baud, 8N1. func (uart *UART) Configure(config UARTConfig) error { + if config.BaudRate != 62500 { + return errors.New("uart: only 62500 baud rate is supported") + } + return nil } From 3a2e740710730f783b480967a10eae08f7ce5598 Mon Sep 17 00:00:00 2001 From: deadprogram Date: Wed, 11 Dec 2024 16:22:52 +0100 Subject: [PATCH 13/15] builder: add tkey to builder test Signed-off-by: deadprogram --- builder/builder_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/builder/builder_test.go b/builder/builder_test.go index 3d714808fa..1d4584c347 100644 --- a/builder/builder_test.go +++ b/builder/builder_test.go @@ -33,6 +33,7 @@ func TestClangAttributes(t *testing.T) { "k210", "nintendoswitch", "riscv-qemu", + "tkey", "wasip1", "wasip2", "wasm", From b06c0979cddc458bf4c45b4e03d336ef5af21cdc Mon Sep 17 00:00:00 2001 From: deadprogram Date: Wed, 11 Dec 2024 16:33:46 +0100 Subject: [PATCH 14/15] targets: be very specific for features passed to LLVM for specific config in use for TKey Signed-off-by: deadprogram --- targets/tkey.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/targets/tkey.json b/targets/tkey.json index aac6b80b46..018950171a 100644 --- a/targets/tkey.json +++ b/targets/tkey.json @@ -1,7 +1,7 @@ { "inherits": ["riscv32"], "build-tags": ["tkey"], - "features": "+c,+zmmul", + "features": "+32bit,+c,+zmmul,-a,-d,-e,-experimental-zacas,-experimental-zcmop,-experimental-zfbfmin,-experimental-zicfilp,-experimental-zicfiss,-experimental-zimop,-experimental-ztso,-experimental-zvfbfmin,-experimental-zvfbfwma,-f,-h,-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,-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", "cflags": [ "-mcmodel=medany", "-march=rv32iczmmul" From 20213d888773d395d564e89334b438479d83fdff Mon Sep 17 00:00:00 2001 From: deadprogram Date: Sat, 14 Dec 2024 13:16:55 +0100 Subject: [PATCH 15/15] targets: handle feedback items from TKey device code review Signed-off-by: deadprogram --- src/machine/machine_tkey.go | 18 ++++++++++-------- src/runtime/runtime_tkey.go | 2 +- src/runtime/runtime_tkey_baremetal.go | 4 ++-- targets/tkey.json | 5 ----- 4 files changed, 13 insertions(+), 16 deletions(-) diff --git a/src/machine/machine_tkey.go b/src/machine/machine_tkey.go index 7a7850385b..78863d845c 100644 --- a/src/machine/machine_tkey.go +++ b/src/machine/machine_tkey.go @@ -84,20 +84,22 @@ func (p Pin) Get() bool { } case GPIO1: mode = gpio1Config.Mode - if tkey.TK1.GPIO.HasBits(1 << uint(p-8)) { - pushed = true - } + pushed = tkey.TK1.GPIO.HasBits(1 << uint(p-8)) case GPIO2: mode = gpio2Config.Mode - if tkey.TK1.GPIO.HasBits(1 << uint(p-8)) { - pushed = true - } + pushed = tkey.TK1.GPIO.HasBits(1 << uint(p-8)) + case GPIO3, GPIO4: + mode = PinOutput + pushed = tkey.TK1.GPIO.HasBits(1 << uint(p-8)) + case LED_BLUE, LED_GREEN, LED_RED: + mode = PinOutput + pushed = tkey.TK1.LED.HasBits(1 << uint(p)) } switch mode { case PinInputPullup: return !pushed - case PinInput, PinInputPulldown: + case PinInput, PinInputPulldown, PinOutput: return pushed } @@ -116,7 +118,7 @@ var ( // The TKey UART is fixed at 62500 baud, 8N1. func (uart *UART) Configure(config UARTConfig) error { - if config.BaudRate != 62500 { + if !(config.BaudRate == 62500 || config.BaudRate == 0) { return errors.New("uart: only 62500 baud rate is supported") } diff --git a/src/runtime/runtime_tkey.go b/src/runtime/runtime_tkey.go index 5cc5c80801..ba8c5e944f 100644 --- a/src/runtime/runtime_tkey.go +++ b/src/runtime/runtime_tkey.go @@ -24,7 +24,7 @@ func main() { func initPeripherals() { // prescaler value that results in 0.00001-second timer-ticks. // given an 18 MHz processor, a millisecond is about 18,000 cycles. - tkey.TIMER.PRESCALER.Set(18_000_000 / 100000) + tkey.TIMER.PRESCALER.Set(18 * machine.MHz / 100000) machine.InitSerial() } diff --git a/src/runtime/runtime_tkey_baremetal.go b/src/runtime/runtime_tkey_baremetal.go index 1498e19c33..a83bd4408d 100644 --- a/src/runtime/runtime_tkey_baremetal.go +++ b/src/runtime/runtime_tkey_baremetal.go @@ -4,12 +4,12 @@ package runtime import "device/riscv" -// ticksToNanoseconds converts ticks (at 18MHz) to nanoseconds. +// ticksToNanoseconds converts ticks (at 18MHz) to 10 µs. func ticksToNanoseconds(ticks timeUnit) int64 { return int64(ticks) * 10000 } -// nanosecondsToTicks converts nanoseconds to ticks (at 18MHz). +// nanosecondsToTicks converts 10 µs to ticks (at 18MHz). func nanosecondsToTicks(ns int64) timeUnit { return timeUnit(ns / 10000) } diff --git a/targets/tkey.json b/targets/tkey.json index 018950171a..f450e6a1b1 100644 --- a/targets/tkey.json +++ b/targets/tkey.json @@ -3,16 +3,11 @@ "build-tags": ["tkey"], "features": "+32bit,+c,+zmmul,-a,-d,-e,-experimental-zacas,-experimental-zcmop,-experimental-zfbfmin,-experimental-zicfilp,-experimental-zicfiss,-experimental-zimop,-experimental-ztso,-experimental-zvfbfmin,-experimental-zvfbfwma,-f,-h,-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,-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", "cflags": [ - "-mcmodel=medany", "-march=rv32iczmmul" ], "linkerscript": "targets/tkey.ld", "scheduler": "none", - "default-stack-size": 2048, "gc": "leaking", - "linker": "ld.lld", - "rtlib": "compiler-rt", - "libc": "picolibc", "flash-command": "tkey-runapp {bin}", "serial": "uart" }