tinygo/src/runtime/runtime_nrf.go
Ayke van Laethem 8d170d3bd2
all: change special type __volatile to pragma //go:volatile
This is one step towards removing unnecessary special casts in most
cases. It is also part of removing as much magic as possible from the
compiler (the pragma is explicit, the special name is not).
2018-09-28 13:17:03 +02:00

109 строки
2,3 КиБ
Go

// +build nrf
package runtime
import (
"device/arm"
"device/nrf"
)
type timeUnit int64
const tickMicros = 1024 * 32
//go:linkname systemInit SystemInit
func systemInit()
//go:export Reset_Handler
func handleReset() {
systemInit()
main()
}
func init() {
initUART()
initLFCLK()
initRTC()
}
func initUART() {
nrf.UART0.ENABLE = nrf.UART_ENABLE_ENABLE_Enabled
nrf.UART0.BAUDRATE = nrf.UART_BAUDRATE_BAUDRATE_Baud115200
nrf.UART0.TASKS_STARTTX = 1
nrf.UART0.PSELTXD = 6 // pin 6 for NRF52840-DK
}
func initLFCLK() {
nrf.CLOCK.LFCLKSRC = nrf.CLOCK_LFCLKSTAT_SRC_Xtal
nrf.CLOCK.TASKS_LFCLKSTART = 1
for nrf.CLOCK.EVENTS_LFCLKSTARTED == 0 {
}
nrf.CLOCK.EVENTS_LFCLKSTARTED = 0
}
func initRTC() {
nrf.RTC0.TASKS_START = 1
// TODO: set priority
arm.EnableIRQ(nrf.IRQ_RTC0)
}
func putchar(c byte) {
nrf.UART0.TXD = nrf.RegValue(c)
for nrf.UART0.EVENTS_TXDRDY == 0 {
}
nrf.UART0.EVENTS_TXDRDY = 0
}
func sleepTicks(d timeUnit) {
for d != 0 {
ticks() // update timestamp
ticks := uint32(d) & 0x7fffff // 23 bits (to be on the safe side)
rtc_sleep(ticks) // TODO: not accurate (must be d / 30.5175...)
d -= timeUnit(ticks)
}
}
var (
timestamp timeUnit // nanoseconds since boottime
rtcLastCounter uint32 // 24 bits ticks
)
// Monotonically increasing numer of ticks since start.
//
// Note: very long pauses between measurements (more than 8 minutes) may
// overflow the counter, leading to incorrect results. This might be fixed by
// handling the overflow event.
func ticks() timeUnit {
rtcCounter := uint32(nrf.RTC0.COUNTER)
offset := (rtcCounter - rtcLastCounter) % 0xffffff // change since last measurement
rtcLastCounter = rtcCounter
timestamp += timeUnit(offset) // TODO: not precise
return timestamp
}
//go:volatile
type isrFlag bool
var rtc_wakeup isrFlag
func rtc_sleep(ticks uint32) {
nrf.RTC0.INTENSET = nrf.RTC_INTENSET_COMPARE0
rtc_wakeup = false
if ticks == 1 {
// Race condition (even in hardware) at ticks == 1.
// TODO: fix this in a better way by detecting it, like the manual
// describes.
ticks = 2
}
nrf.RTC0.CC[0] = (nrf.RTC0.COUNTER + nrf.RegValue(ticks)) & 0x00ffffff
for !rtc_wakeup {
arm.Asm("wfi")
}
}
//go:export RTC0_IRQHandler
func handleRTC0() {
nrf.RTC0.INTENCLR = nrf.RTC_INTENSET_COMPARE0
nrf.RTC0.EVENTS_COMPARE[0] = 0
rtc_wakeup = true
}