avr: simplify timer-based time
Simplify the interrupt-based timer code in a few ways: - Do not recalibrate the timer every 100ms. Instead, rely on the fact that the machine package will calbrate the timer if necessary if it makes changes to Timer0. - Do not configure Timer0 and then set nanosecondsInTick based on that value. Instead, use a fixed value. These two changes together mean that in code that doesn't use PWM, nanosecondsInTick will be constant which makes the TIMER0_OVF interrupt handler a lot smaller. Together this reduces the code size of AVR binaries by about 1200 bytes, making it pretty close to the pre-timer code size (only about 250 bytes larger). It also somehow fixes a problem with tinygo.org/x/drivers/examples/ws2812 on the Arduino Uno. I'm not quite sure what was going wrong, but bisecting pointed towards the timer code (https://github.com/tinygo-org/tinygo/pull/2428) and with this simplification the bug appears to be gone.
Этот коммит содержится в:
родитель
52c61de19f
коммит
9de76fb42e
1 изменённых файлов: 6 добавлений и 15 удалений
|
@ -77,14 +77,6 @@ func nanosecondsToTicks(ns int64) timeUnit {
|
||||||
// Sleep this number of ticks of nanoseconds.
|
// Sleep this number of ticks of nanoseconds.
|
||||||
func sleepTicks(d timeUnit) {
|
func sleepTicks(d timeUnit) {
|
||||||
waitTill := ticks() + d
|
waitTill := ticks() + d
|
||||||
// recalibrate if we have some time (>100ms) and it was a while when we did it last time.
|
|
||||||
if d > 100000 {
|
|
||||||
now := waitTill - d
|
|
||||||
if nextTimerRecalibrate < now {
|
|
||||||
nextTimerRecalibrate = now + timerRecalibrateInterval
|
|
||||||
adjustMonotonicTimer()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for {
|
for {
|
||||||
// wait for interrupt
|
// wait for interrupt
|
||||||
avr.Asm("sleep")
|
avr.Asm("sleep")
|
||||||
|
@ -120,18 +112,17 @@ func abort() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var ticksCount int64 // nanoseconds since start
|
var ticksCount int64 // nanoseconds since start
|
||||||
var nanosecondsInTick int64 // nanoseconds per each tick
|
var nanosecondsInTick int64 = 16000 // nanoseconds per each tick
|
||||||
|
|
||||||
func initMonotonicTimer() {
|
func initMonotonicTimer() {
|
||||||
nanosecondsInTick = 0
|
|
||||||
ticksCount = 0
|
ticksCount = 0
|
||||||
|
|
||||||
interrupt.New(avr.IRQ_TIMER0_OVF, func(i interrupt.Interrupt) {
|
interrupt.New(avr.IRQ_TIMER0_OVF, func(i interrupt.Interrupt) {
|
||||||
// use volatile
|
// use volatile
|
||||||
increment := volatile.LoadUint64((*uint64)(unsafe.Pointer(&nanosecondsInTick)))
|
|
||||||
ticks := volatile.LoadUint64((*uint64)(unsafe.Pointer(&ticksCount)))
|
ticks := volatile.LoadUint64((*uint64)(unsafe.Pointer(&ticksCount)))
|
||||||
volatile.StoreUint64((*uint64)(unsafe.Pointer(&ticksCount)), ticks+increment)
|
ticks += uint64(nanosecondsInTick)
|
||||||
|
volatile.StoreUint64((*uint64)(unsafe.Pointer(&ticksCount)), ticks)
|
||||||
})
|
})
|
||||||
|
|
||||||
// initial initialization of the Timer0
|
// initial initialization of the Timer0
|
||||||
|
@ -146,8 +137,6 @@ func initMonotonicTimer() {
|
||||||
// - Set prescaler 1
|
// - Set prescaler 1
|
||||||
avr.TCCR0B.Set(avr.TCCR0B_CS00)
|
avr.TCCR0B.Set(avr.TCCR0B_CS00)
|
||||||
|
|
||||||
adjustMonotonicTimer()
|
|
||||||
|
|
||||||
// - Unmask interrupt
|
// - Unmask interrupt
|
||||||
avr.TIMSK0.SetBits(avr.TIMSK0_TOIE0)
|
avr.TIMSK0.SetBits(avr.TIMSK0_TOIE0)
|
||||||
}
|
}
|
||||||
|
@ -155,7 +144,9 @@ func initMonotonicTimer() {
|
||||||
//go:linkname adjustMonotonicTimer machine.adjustMonotonicTimer
|
//go:linkname adjustMonotonicTimer machine.adjustMonotonicTimer
|
||||||
func adjustMonotonicTimer() {
|
func adjustMonotonicTimer() {
|
||||||
// adjust the nanosecondsInTick using volatile
|
// adjust the nanosecondsInTick using volatile
|
||||||
|
mask := interrupt.Disable()
|
||||||
volatile.StoreUint64((*uint64)(unsafe.Pointer(&nanosecondsInTick)), uint64(currentNanosecondsInTick()))
|
volatile.StoreUint64((*uint64)(unsafe.Pointer(&nanosecondsInTick)), uint64(currentNanosecondsInTick()))
|
||||||
|
interrupt.Restore(mask)
|
||||||
}
|
}
|
||||||
|
|
||||||
func currentNanosecondsInTick() int64 {
|
func currentNanosecondsInTick() int64 {
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче