mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-24 22:39:04 +00:00
targets: add implementation for Tillitis TKey device (#4631)
* initial implementation for Tillitis TKey device * add UART implementation for TKey * add Pin interface implementation for TKey touch sensor * add RNG interface implementation for TKey * add helpful machine package functions to return identifiers such as name and version for TKey * use built-in timer for sleep timing on TKey * modify UART implementation for TKey to implement Serialer interface * implement BLAKE2s ROM function call for TKey device * handle abort by triggering TKey device fault using illegal instruction to halt CPU * simplify TKey implementation by inheriting from existing riscv32 target * return error for trying to configure invalid baudrates on UART * add tkey to builder test * be very specific for features passed to LLVM for specific config in use for TKey * handle feedback items from TKey device code review Signed-off-by: deadprogram <ron@hybridgroup.com>
This commit is contained in:
@@ -853,6 +853,8 @@ endif
|
|||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=maixbit examples/blinky1
|
$(TINYGO) build -size short -o test.hex -target=maixbit examples/blinky1
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
|
$(TINYGO) build -size short -o test.hex -target=tkey examples/blinky1
|
||||||
|
@$(MD5SUM) test.hex
|
||||||
ifneq ($(WASM), 0)
|
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/export
|
||||||
$(TINYGO) build -size short -o wasm.wasm -target=wasm examples/wasm/main
|
$(TINYGO) build -size short -o wasm.wasm -target=wasm examples/wasm/main
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ func TestClangAttributes(t *testing.T) {
|
|||||||
"k210",
|
"k210",
|
||||||
"nintendoswitch",
|
"nintendoswitch",
|
||||||
"riscv-qemu",
|
"riscv-qemu",
|
||||||
|
"tkey",
|
||||||
"wasip1",
|
"wasip1",
|
||||||
"wasip2",
|
"wasip2",
|
||||||
"wasm",
|
"wasm",
|
||||||
|
|||||||
@@ -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
|
// If you update the above build constraint, you'll probably also need to update
|
||||||
// src/runtime/rand_hwrng.go.
|
// src/runtime/rand_hwrng.go.
|
||||||
|
|||||||
@@ -0,0 +1,139 @@
|
|||||||
|
//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.Register32
|
||||||
|
_ [88]byte
|
||||||
|
ENTROPY volatile.Register32
|
||||||
|
}
|
||||||
|
|
||||||
|
type TIMER_Type struct {
|
||||||
|
_ [32]byte
|
||||||
|
CTRL volatile.Register32
|
||||||
|
STATUS volatile.Register32
|
||||||
|
PRESCALER volatile.Register32
|
||||||
|
TIMER volatile.Register32
|
||||||
|
}
|
||||||
|
|
||||||
|
type UDS_Type struct {
|
||||||
|
_ [64]byte
|
||||||
|
DATA [8]volatile.Register32
|
||||||
|
}
|
||||||
|
|
||||||
|
type UART_Type struct {
|
||||||
|
_ [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 {
|
||||||
|
_ [36]byte
|
||||||
|
STATUS volatile.Register32
|
||||||
|
}
|
||||||
|
|
||||||
|
type TK1_Type struct {
|
||||||
|
NAME0 volatile.Register32
|
||||||
|
NAME1 volatile.Register32
|
||||||
|
VERSION volatile.Register32
|
||||||
|
_ [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
|
||||||
|
_ [72]byte
|
||||||
|
CDI_FIRST [8]volatile.Register32
|
||||||
|
_ [32]byte
|
||||||
|
UDI_FIRST [2]volatile.Register32
|
||||||
|
_ [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.Register32
|
||||||
|
SPI_XFER volatile.Register32
|
||||||
|
SPI_DATA volatile.Register32
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
TK1_MMIO_TK1_GPIO1_BIT = 0
|
||||||
|
TK1_MMIO_TK1_GPIO2_BIT = 1
|
||||||
|
TK1_MMIO_TK1_GPIO3_BIT = 2
|
||||||
|
TK1_MMIO_TK1_GPIO4_BIT = 3
|
||||||
|
)
|
||||||
@@ -0,0 +1,234 @@
|
|||||||
|
//go:build tkey
|
||||||
|
|
||||||
|
package machine
|
||||||
|
|
||||||
|
import (
|
||||||
|
"device/tkey"
|
||||||
|
"errors"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
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
|
||||||
|
)
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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 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:
|
||||||
|
touchConfig = config
|
||||||
|
|
||||||
|
// Clear any pending touch events.
|
||||||
|
tkey.TOUCH.STATUS.Set(0)
|
||||||
|
case GPIO1:
|
||||||
|
gpio1Config = config
|
||||||
|
case GPIO2:
|
||||||
|
gpio2Config = config
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set 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))
|
||||||
|
}
|
||||||
|
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:
|
||||||
|
mode = touchConfig.Mode
|
||||||
|
if tkey.TOUCH.STATUS.HasBits(1) {
|
||||||
|
tkey.TOUCH.STATUS.Set(0)
|
||||||
|
pushed = true
|
||||||
|
}
|
||||||
|
case GPIO1:
|
||||||
|
mode = gpio1Config.Mode
|
||||||
|
pushed = tkey.TK1.GPIO.HasBits(1 << uint(p-8))
|
||||||
|
case GPIO2:
|
||||||
|
mode = gpio2Config.Mode
|
||||||
|
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, PinOutput:
|
||||||
|
return pushed
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
type UART struct {
|
||||||
|
Bus *tkey.UART_Type
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
DefaultUART = UART0
|
||||||
|
UART0 = &_UART0
|
||||||
|
_UART0 = UART{Bus: tkey.UART}
|
||||||
|
)
|
||||||
|
|
||||||
|
// The TKey UART is fixed at 62500 baud, 8N1.
|
||||||
|
func (uart *UART) Configure(config UARTConfig) error {
|
||||||
|
if !(config.BaudRate == 62500 || config.BaudRate == 0) {
|
||||||
|
return errors.New("uart: only 62500 baud rate is supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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 {
|
||||||
|
}
|
||||||
|
|
||||||
|
uart.Bus.TX_DATA.Set(uint32(c))
|
||||||
|
|
||||||
|
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 {
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -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
|
// If you update the above build constraint, you'll probably also need to update
|
||||||
// src/crypto/rand/rand_baremetal.go.
|
// src/crypto/rand/rand_baremetal.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
|
package runtime
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
//go:build tkey
|
||||||
|
|
||||||
|
// This file implements target-specific things for the TKey.
|
||||||
|
|
||||||
|
package runtime
|
||||||
|
|
||||||
|
import (
|
||||||
|
"device/tkey"
|
||||||
|
"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() {
|
||||||
|
// 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 * machine.MHz / 100000)
|
||||||
|
|
||||||
|
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 := uint32(ticks() + d)
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
//go:build tkey && !qemu
|
||||||
|
|
||||||
|
package runtime
|
||||||
|
|
||||||
|
import "device/riscv"
|
||||||
|
|
||||||
|
// ticksToNanoseconds converts ticks (at 18MHz) to 10 µs.
|
||||||
|
func ticksToNanoseconds(ticks timeUnit) int64 {
|
||||||
|
return int64(ticks) * 10000
|
||||||
|
}
|
||||||
|
|
||||||
|
// nanosecondsToTicks converts 10 µs to ticks (at 18MHz).
|
||||||
|
func nanosecondsToTicks(ns int64) timeUnit {
|
||||||
|
return timeUnit(ns / 10000)
|
||||||
|
}
|
||||||
|
|
||||||
|
func exit(code int) {
|
||||||
|
abort()
|
||||||
|
}
|
||||||
|
|
||||||
|
func abort() {
|
||||||
|
// Force illegal instruction to halt CPU
|
||||||
|
riscv.Asm("unimp")
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"inherits": ["riscv32"],
|
||||||
|
"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": [
|
||||||
|
"-march=rv32iczmmul"
|
||||||
|
],
|
||||||
|
"linkerscript": "targets/tkey.ld",
|
||||||
|
"scheduler": "none",
|
||||||
|
"gc": "leaking",
|
||||||
|
"flash-command": "tkey-runapp {bin}",
|
||||||
|
"serial": "uart"
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
RAM (rwx) : ORIGIN = 0x40000000, LENGTH = 0x20000 /* 128 KB */
|
||||||
|
}
|
||||||
|
|
||||||
|
REGION_ALIAS("FLASH_TEXT", RAM);
|
||||||
|
|
||||||
|
_stack_size = 2K;
|
||||||
|
|
||||||
|
INCLUDE "targets/riscv.ld"
|
||||||
Reference in New Issue
Block a user