mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-06 20:13:40 +00:00
3c55689566
This commit refactors both determining the current time and sleeping for
a given time. It also improves precision for many chips.
* The nrf chips had a long-standing TODO comment about a slightly
inaccurate clock. This should now be fixed.
* The SAM D2x/D5x chips may have a slightly more accurate clock,
although probably within the error margin of the RTC. Also, by
working with RTC ticks and converting in the least number of places,
code size is often slightly reduced (usually just a few bytes, up to
around 1kB in some cases).
* I believe the HiFive1 rev B timer was slightly wrong (32768Hz vs
30517.6Hz). Because the datasheet says the clock runs at 32768Hz,
I've used the same conversion code here as in the nrf and sam cases.
* I couldn't test both stm32 timers, so I kept them as they currently
are. It may be possible to make them more efficient by using the
native tick frequency instead of using microseconds everywhere.
103 lines
1.6 KiB
Go
103 lines
1.6 KiB
Go
// +build avr
|
|
|
|
package runtime
|
|
|
|
import (
|
|
"device/avr"
|
|
"machine"
|
|
"unsafe"
|
|
)
|
|
|
|
const BOARD = "arduino"
|
|
|
|
type timeUnit uint32
|
|
|
|
var currentTime timeUnit
|
|
|
|
// Watchdog timer periods. These can be off by a large margin (hence the jump
|
|
// between 64ms and 125ms which is not an exact double), so don't rely on this
|
|
// for accurate time keeping.
|
|
const (
|
|
WDT_PERIOD_16MS = iota
|
|
WDT_PERIOD_32MS
|
|
WDT_PERIOD_64MS
|
|
WDT_PERIOD_125MS
|
|
WDT_PERIOD_250MS
|
|
WDT_PERIOD_500MS
|
|
WDT_PERIOD_1S
|
|
WDT_PERIOD_2S
|
|
)
|
|
|
|
//go:extern _sbss
|
|
var _sbss [0]byte
|
|
|
|
//go:extern _ebss
|
|
var _ebss [0]byte
|
|
|
|
//export main
|
|
func main() {
|
|
preinit()
|
|
run()
|
|
abort()
|
|
}
|
|
|
|
func preinit() {
|
|
// Initialize .bss: zero-initialized global variables.
|
|
ptr := unsafe.Pointer(&_sbss)
|
|
for ptr != unsafe.Pointer(&_ebss) {
|
|
*(*uint8)(ptr) = 0
|
|
ptr = unsafe.Pointer(uintptr(ptr) + 1)
|
|
}
|
|
}
|
|
|
|
func postinit() {
|
|
// Enable interrupts after initialization.
|
|
avr.Asm("sei")
|
|
}
|
|
|
|
func init() {
|
|
initUART()
|
|
}
|
|
|
|
func initUART() {
|
|
machine.UART0.Configure(machine.UARTConfig{})
|
|
}
|
|
|
|
func putchar(c byte) {
|
|
machine.UART0.WriteByte(c)
|
|
}
|
|
|
|
const asyncScheduler = false
|
|
|
|
const tickNanos = 1024 * 16384 // roughly 16ms in nanoseconds
|
|
|
|
func ticksToNanoseconds(ticks timeUnit) int64 {
|
|
return int64(ticks) * tickNanos
|
|
}
|
|
|
|
func nanosecondsToTicks(ns int64) timeUnit {
|
|
return timeUnit(ns / tickNanos)
|
|
}
|
|
|
|
// Sleep this number of ticks of 16ms.
|
|
//
|
|
// TODO: not very accurate. Improve accuracy by calibrating on startup and every
|
|
// once in a while.
|
|
func sleepTicks(d timeUnit) {
|
|
currentTime += d
|
|
for d != 0 {
|
|
sleepWDT(WDT_PERIOD_16MS)
|
|
d -= 1
|
|
}
|
|
}
|
|
|
|
func ticks() timeUnit {
|
|
return currentTime
|
|
}
|
|
|
|
func abort() {
|
|
for {
|
|
sleepWDT(WDT_PERIOD_2S)
|
|
}
|
|
}
|