mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-09 13:33:39 +00:00
8cd2a462b9
There is no reason to specialize this per chip as it is only ever used for JavaScript. Not only that, it is causing confusion and is yet another quirk to learn when porting the runtime to a new microcontroller.
68 lines
1.3 KiB
Go
68 lines
1.3 KiB
Go
// +build tinygo.riscv,virt,qemu
|
|
|
|
package runtime
|
|
|
|
import (
|
|
"device/riscv"
|
|
"runtime/volatile"
|
|
"unsafe"
|
|
)
|
|
|
|
// This file implements the VirtIO RISC-V interface implemented in QEMU, which
|
|
// is an interface designed for emulation.
|
|
|
|
type timeUnit int64
|
|
|
|
var timestamp timeUnit
|
|
|
|
func postinit() {}
|
|
|
|
//export main
|
|
func main() {
|
|
preinit()
|
|
run()
|
|
abort()
|
|
}
|
|
|
|
func ticksToNanoseconds(ticks timeUnit) int64 {
|
|
return int64(ticks)
|
|
}
|
|
|
|
func nanosecondsToTicks(ns int64) timeUnit {
|
|
return timeUnit(ns)
|
|
}
|
|
|
|
func sleepTicks(d timeUnit) {
|
|
// TODO: actually sleep here for the given time.
|
|
timestamp += d
|
|
}
|
|
|
|
func ticks() timeUnit {
|
|
return timestamp
|
|
}
|
|
|
|
// Memory-mapped I/O as defined by QEMU.
|
|
// Source: https://github.com/qemu/qemu/blob/master/hw/riscv/virt.c
|
|
// Technically this is an implementation detail but hopefully they won't change
|
|
// the memory-mapped I/O registers.
|
|
var (
|
|
// UART0 output register.
|
|
stdoutWrite = (*volatile.Register8)(unsafe.Pointer(uintptr(0x10000000)))
|
|
// SiFive test finisher
|
|
testFinisher = (*volatile.Register16)(unsafe.Pointer(uintptr(0x100000)))
|
|
)
|
|
|
|
func putchar(c byte) {
|
|
stdoutWrite.Set(uint8(c))
|
|
}
|
|
|
|
func abort() {
|
|
// Make sure the QEMU process exits.
|
|
testFinisher.Set(0x5555) // FINISHER_PASS
|
|
|
|
// Lock up forever (as a fallback).
|
|
for {
|
|
riscv.Asm("wfi")
|
|
}
|
|
}
|