github.com/aykevl/tinygo@v0.5.0/src/runtime/runtime_nrf.go (about) 1 // +build nrf 2 3 package runtime 4 5 import ( 6 "device/arm" 7 "device/nrf" 8 "machine" 9 ) 10 11 type timeUnit int64 12 13 const tickMicros = 1024 * 32 14 15 //go:linkname systemInit SystemInit 16 func systemInit() 17 18 //go:export Reset_Handler 19 func main() { 20 systemInit() 21 preinit() 22 initAll() 23 callMain() 24 abort() 25 } 26 27 func init() { 28 machine.UART0.Configure(machine.UARTConfig{}) 29 initLFCLK() 30 initRTC() 31 } 32 33 func initLFCLK() { 34 if machine.HasLowFrequencyCrystal { 35 nrf.CLOCK.LFCLKSRC = nrf.CLOCK_LFCLKSTAT_SRC_Xtal 36 } 37 nrf.CLOCK.TASKS_LFCLKSTART = 1 38 for nrf.CLOCK.EVENTS_LFCLKSTARTED == 0 { 39 } 40 nrf.CLOCK.EVENTS_LFCLKSTARTED = 0 41 } 42 43 func initRTC() { 44 nrf.RTC1.TASKS_START = 1 45 arm.SetPriority(nrf.IRQ_RTC1, 0xc0) // low priority 46 arm.EnableIRQ(nrf.IRQ_RTC1) 47 } 48 49 func putchar(c byte) { 50 machine.UART0.WriteByte(c) 51 } 52 53 const asyncScheduler = false 54 55 func sleepTicks(d timeUnit) { 56 for d != 0 { 57 ticks() // update timestamp 58 ticks := uint32(d) & 0x7fffff // 23 bits (to be on the safe side) 59 rtc_sleep(ticks) // TODO: not accurate (must be d / 30.5175...) 60 d -= timeUnit(ticks) 61 } 62 } 63 64 var ( 65 timestamp timeUnit // nanoseconds since boottime 66 rtcLastCounter uint32 // 24 bits ticks 67 ) 68 69 // Monotonically increasing numer of ticks since start. 70 // 71 // Note: very long pauses between measurements (more than 8 minutes) may 72 // overflow the counter, leading to incorrect results. This might be fixed by 73 // handling the overflow event. 74 func ticks() timeUnit { 75 rtcCounter := uint32(nrf.RTC1.COUNTER) 76 offset := (rtcCounter - rtcLastCounter) & 0xffffff // change since last measurement 77 rtcLastCounter = rtcCounter 78 timestamp += timeUnit(offset) // TODO: not precise 79 return timestamp 80 } 81 82 //go:volatile 83 type isrFlag bool 84 85 var rtc_wakeup isrFlag 86 87 func rtc_sleep(ticks uint32) { 88 nrf.RTC1.INTENSET = nrf.RTC_INTENSET_COMPARE0 89 rtc_wakeup = false 90 if ticks == 1 { 91 // Race condition (even in hardware) at ticks == 1. 92 // TODO: fix this in a better way by detecting it, like the manual 93 // describes. 94 ticks = 2 95 } 96 nrf.RTC1.CC[0] = (nrf.RTC1.COUNTER + nrf.RegValue(ticks)) & 0x00ffffff 97 for !rtc_wakeup { 98 arm.Asm("wfi") 99 } 100 } 101 102 //go:export RTC1_IRQHandler 103 func handleRTC1() { 104 nrf.RTC1.INTENCLR = nrf.RTC_INTENSET_COMPARE0 105 nrf.RTC1.EVENTS_COMPARE[0] = 0 106 rtc_wakeup = true 107 }