121 строка
		
	
	
	
		
			2,2 КиБ
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			121 строка
		
	
	
	
		
			2,2 КиБ
		
	
	
	
		
			Go
		
	
	
	
	
	
| //go:build avr
 | |
| // +build avr
 | |
| 
 | |
| package runtime
 | |
| 
 | |
| import (
 | |
| 	"device/avr"
 | |
| 	"machine"
 | |
| 	"runtime/interrupt"
 | |
| 	"unsafe"
 | |
| )
 | |
| 
 | |
| const BOARD = "arduino"
 | |
| 
 | |
| // timeUnit in nanoseconds
 | |
| type timeUnit int64
 | |
| 
 | |
| // 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
 | |
| )
 | |
| 
 | |
| const timerRecalibrateInterval = 6e7 // 1 minute
 | |
| 
 | |
| var nextTimerRecalibrate timeUnit
 | |
| 
 | |
| //go:extern _sbss
 | |
| var _sbss [0]byte
 | |
| 
 | |
| //go:extern _ebss
 | |
| var _ebss [0]byte
 | |
| 
 | |
| //export main
 | |
| func main() {
 | |
| 	preinit()
 | |
| 	run()
 | |
| 	exit(0)
 | |
| }
 | |
| 
 | |
| 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()
 | |
| 	machine.InitMonotonicTimer()
 | |
| 	nextTimerRecalibrate = ticks() + timerRecalibrateInterval
 | |
| }
 | |
| 
 | |
| func ticksToNanoseconds(ticks timeUnit) int64 {
 | |
| 	return int64(ticks)
 | |
| }
 | |
| 
 | |
| func nanosecondsToTicks(ns int64) timeUnit {
 | |
| 	return timeUnit(ns)
 | |
| }
 | |
| 
 | |
| // Sleep this number of ticks of nanoseconds.
 | |
| func sleepTicks(d timeUnit) {
 | |
| 	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
 | |
| 			machine.AdjustMonotonicTimer()
 | |
| 		}
 | |
| 	}
 | |
| 	for {
 | |
| 		// wait for interrupt
 | |
| 		avr.Asm("sleep")
 | |
| 		if waitTill <= ticks() {
 | |
| 			// done waiting
 | |
| 			return
 | |
| 		}
 | |
| 		if hasScheduler {
 | |
| 			// The interrupt may have awoken a goroutine, so bail out early.
 | |
| 			return
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // ticks return time since start in nanoseconds
 | |
| func ticks() (ticks timeUnit) {
 | |
| 	state := interrupt.Disable()
 | |
| 	ticks = timeUnit(machine.Ticks)
 | |
| 	interrupt.Restore(state)
 | |
| 	return
 | |
| }
 | |
| 
 | |
| func exit(code int) {
 | |
| 	abort()
 | |
| }
 | |
| 
 | |
| func abort() {
 | |
| 	// Disable interrupts and go to sleep.
 | |
| 	// This can never be awoken except for reset, and is recogized as termination by simavr.
 | |
| 	avr.Asm("cli")
 | |
| 	for {
 | |
| 		avr.Asm("sleep")
 | |
| 	}
 | |
| }
 | 
