tinygo/src/runtime/runtime_fe310.go
Ayke van Laethem a04db67ea9 runtime: work around a bug in LLVM for .bss zeroing
See the following bug: https://bugs.llvm.org/show_bug.cgi?id=42881

I think this is a bug in LLVM, but the code in question wasn't the best
code anyway. By fixing this, about 16 bytes of code are saved on ARM
chips (and much more on AVR).
2019-08-05 10:07:46 +02:00

115 строки
2,3 КиБ
Go

// +build fe310
// This file implements target-specific things for the FE310 chip as used in the
// HiFive1.
package runtime
import (
"machine"
"unsafe"
"device/riscv"
"device/sifive"
)
type timeUnit int64
const tickMicros = 32768 // RTC runs at 32.768kHz
//go:extern _sbss
var _sbss unsafe.Pointer
//go:extern _ebss
var _ebss unsafe.Pointer
//go:extern _sdata
var _sdata unsafe.Pointer
//go:extern _sidata
var _sidata unsafe.Pointer
//go:extern _edata
var _edata unsafe.Pointer
//go:export main
func main() {
preinit()
initAll()
callMain()
abort()
}
func init() {
pric_init()
machine.UART0.Configure(machine.UARTConfig{})
}
func pric_init() {
// Make sure the HFROSC is on
sifive.PRIC.HFROSCCFG.SetBits(sifive.PRIC_HFROSCCFG_ENABLE)
// Run off 16 MHz Crystal for accuracy.
sifive.PRIC.PLLCFG.SetBits(sifive.PRIC_PLLCFG_REFSEL | sifive.PRIC_PLLCFG_BYPASS)
sifive.PRIC.PLLCFG.SetBits(sifive.PRIC_PLLCFG_SEL)
// Turn off HFROSC to save power
sifive.PRIC.HFROSCCFG.ClearBits(sifive.PRIC_HFROSCCFG_ENABLE)
// Enable the RTC.
sifive.RTC.CONFIG.Set(sifive.RTC_CONFIG_ENALWAYS)
}
func preinit() {
// Initialize .bss: zero-initialized global variables.
ptr := unsafe.Pointer(&_sbss)
for ptr != unsafe.Pointer(&_ebss) {
*(*uint32)(ptr) = 0
ptr = unsafe.Pointer(uintptr(ptr) + 4)
}
// Initialize .data: global variables initialized from flash.
src := unsafe.Pointer(&_sidata)
dst := unsafe.Pointer(&_sdata)
for dst != unsafe.Pointer(&_edata) {
*(*uint32)(dst) = *(*uint32)(src)
dst = unsafe.Pointer(uintptr(dst) + 4)
src = unsafe.Pointer(uintptr(src) + 4)
}
}
func putchar(c byte) {
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.HI.Get()
for {
lowBits := sifive.RTC.LO.Get()
newHighBits := sifive.RTC.HI.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
func sleepTicks(d timeUnit) {
target := ticks() + d
for ticks() < target {
}
}
func abort() {
// lock up forever
for {
riscv.Asm("wfi")
}
}