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  }