riscv: support sleeping in QEMU
QEMU doesn't support the RTC peripheral yet so work around it for now. This makes the following command work: tinygo run -target=hifive1-qemu ./testdata/coroutines.go
Этот коммит содержится в:
родитель
14474e7099
коммит
184827e4d8
3 изменённых файлов: 37 добавлений и 23 удалений
|
@ -81,27 +81,4 @@ func putchar(c byte) {
|
||||||
machine.UART0.WriteByte(c)
|
machine.UART0.WriteByte(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ticks() timeUnit {
|
|
||||||
// Combining the low bits and the high bits yields a time span of over 270
|
|
||||||
// years without counter rollover.
|
|
||||||
highBits := sifive.RTC.RTCHI.Get()
|
|
||||||
for {
|
|
||||||
lowBits := sifive.RTC.RTCLO.Get()
|
|
||||||
newHighBits := sifive.RTC.RTCHI.Get()
|
|
||||||
if newHighBits == highBits {
|
|
||||||
// High bits stayed the same.
|
|
||||||
return timeUnit(lowBits) | (timeUnit(highBits) << 32)
|
|
||||||
}
|
|
||||||
// Retry, because there was a rollover in the low bits (happening every
|
|
||||||
// 1.5 days).
|
|
||||||
highBits = newHighBits
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const asyncScheduler = false
|
const asyncScheduler = false
|
||||||
|
|
||||||
func sleepTicks(d timeUnit) {
|
|
||||||
target := ticks() + d
|
|
||||||
for ticks() < target {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ package runtime
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"device/riscv"
|
"device/riscv"
|
||||||
|
"device/sifive"
|
||||||
)
|
)
|
||||||
|
|
||||||
func abort() {
|
func abort() {
|
||||||
|
@ -12,3 +13,27 @@ func abort() {
|
||||||
riscv.Asm("wfi")
|
riscv.Asm("wfi")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ticks() timeUnit {
|
||||||
|
// Combining the low bits and the high bits yields a time span of over 270
|
||||||
|
// years without counter rollover.
|
||||||
|
highBits := sifive.RTC.RTCHI.Get()
|
||||||
|
for {
|
||||||
|
lowBits := sifive.RTC.RTCLO.Get()
|
||||||
|
newHighBits := sifive.RTC.RTCHI.Get()
|
||||||
|
if newHighBits == highBits {
|
||||||
|
// High bits stayed the same.
|
||||||
|
println("bits:", highBits, lowBits)
|
||||||
|
return timeUnit(lowBits) | (timeUnit(highBits) << 32)
|
||||||
|
}
|
||||||
|
// Retry, because there was a rollover in the low bits (happening every
|
||||||
|
// 1.5 days).
|
||||||
|
highBits = newHighBits
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func sleepTicks(d timeUnit) {
|
||||||
|
target := ticks() + d
|
||||||
|
for ticks() < target {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -10,7 +10,19 @@ import (
|
||||||
// Special memory-mapped device to exit tests, created by SiFive.
|
// Special memory-mapped device to exit tests, created by SiFive.
|
||||||
var testExit = (*volatile.Register32)(unsafe.Pointer(uintptr(0x100000)))
|
var testExit = (*volatile.Register32)(unsafe.Pointer(uintptr(0x100000)))
|
||||||
|
|
||||||
|
var timestamp timeUnit
|
||||||
|
|
||||||
func abort() {
|
func abort() {
|
||||||
// Signal a successful exit.
|
// Signal a successful exit.
|
||||||
testExit.Set(0x5555)
|
testExit.Set(0x5555)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ticks() timeUnit {
|
||||||
|
return timestamp
|
||||||
|
}
|
||||||
|
|
||||||
|
func sleepTicks(d timeUnit) {
|
||||||
|
// Note: QEMU doesn't seem to support the RTC peripheral at the time of
|
||||||
|
// writing so just simulate sleeping here.
|
||||||
|
timestamp += d
|
||||||
|
}
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче