Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

targets: initial implementation for Tillitis TKey device #4631

Open
wants to merge 6 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/crypto/rand/rand_baremetal.go
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
53 changes: 53 additions & 0 deletions src/device/tkey/crt0.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
// 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
134 changes: 134 additions & 0 deletions src/device/tkey/tkey.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
//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
)
186 changes: 186 additions & 0 deletions src/machine/machine_tkey.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
//go:build tkey

package machine

import (
"device/tkey"
"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
)

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.
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))
}
}
}

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
}

var (
DefaultUART = UART0
UART0 = &_UART0
_UART0 = UART{Bus: tkey.UART}
)

// Thw TKey UART is fixed at 62500 baud, 8N1.
func (uart *UART) Configure(config UARTConfig) {
}

func (uart *UART) SetBaudRate(br uint32) {
}

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(uint32(c))

return nil
}

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
}

// 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
}
2 changes: 1 addition & 1 deletion src/runtime/rand_hwrng.go
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
Loading