teensy40: init RTC and use ARM cycle counter for improved SysTick accuracy
Этот коммит содержится в:
родитель
0d9c46b59e
коммит
47410a4b54
2 изменённых файлов: 38 добавлений и 11 удалений
|
@ -108,6 +108,7 @@ func initPeripherals() {
|
||||||
|
|
||||||
enableTimerClocks() // activate GPT/PIT clock gates
|
enableTimerClocks() // activate GPT/PIT clock gates
|
||||||
initSysTick() // enable SysTick
|
initSysTick() // enable SysTick
|
||||||
|
initRTC() // enable real-time clock
|
||||||
|
|
||||||
enablePinClocks() // activate IOMUXC(_GPR)/GPIO clock gates
|
enablePinClocks() // activate IOMUXC(_GPR)/GPIO clock gates
|
||||||
initPins() // configure GPIO
|
initPins() // configure GPIO
|
||||||
|
|
|
@ -7,13 +7,14 @@ import (
|
||||||
"device/nxp"
|
"device/nxp"
|
||||||
"runtime/interrupt"
|
"runtime/interrupt"
|
||||||
"runtime/volatile"
|
"runtime/volatile"
|
||||||
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
type timeUnit int64
|
type timeUnit int64
|
||||||
|
|
||||||
const ( // HW divides 24 MHz XTALOSC down to 100 kHz
|
const ( // HW divides 24 MHz XTALOSC down to 100 kHz
|
||||||
lastCycle = SYSTICK_FREQ/1000 - 1
|
lastCycle = SYSTICK_FREQ/1000 - 1
|
||||||
microsPerCycle = 1000000 / SYSTICK_FREQ
|
cyclesPerMicro = CORE_FREQ / 1000000
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -24,10 +25,23 @@ const (
|
||||||
|
|
||||||
var (
|
var (
|
||||||
tickCount volatile.Register64
|
tickCount volatile.Register64
|
||||||
|
cycleCount volatile.Register32
|
||||||
pitActive volatile.Register32
|
pitActive volatile.Register32
|
||||||
pitTimeout interrupt.Interrupt
|
pitTimeout interrupt.Interrupt
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// debug exception and monitor control
|
||||||
|
DEMCR = (*volatile.Register32)(unsafe.Pointer(uintptr(0xe000edfc)))
|
||||||
|
DWT_CTRL = (*volatile.Register32)(unsafe.Pointer(uintptr(0xe0001000)))
|
||||||
|
DWT_CYCCNT = (*volatile.Register32)(unsafe.Pointer(uintptr(0xe0001004)))
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
DEMCR_TRCENA = 0x01000000 // enable debugging & monitoring blocks
|
||||||
|
DWT_CTRL_CYCCNTENA = 0x00000001 // cycle count register
|
||||||
|
)
|
||||||
|
|
||||||
func ticksToNanoseconds(ticks timeUnit) int64 {
|
func ticksToNanoseconds(ticks timeUnit) int64 {
|
||||||
return int64(ticks) * 1000
|
return int64(ticks) * 1000
|
||||||
}
|
}
|
||||||
|
@ -49,6 +63,12 @@ func initSysTick() {
|
||||||
// set SysTick and PendSV priority to 32
|
// set SysTick and PendSV priority to 32
|
||||||
nxp.SystemControl.SHPR3.Set((0x20 << nxp.SCB_SHPR3_PRI_15_Pos) |
|
nxp.SystemControl.SHPR3.Set((0x20 << nxp.SCB_SHPR3_PRI_15_Pos) |
|
||||||
(0x20 << nxp.SCB_SHPR3_PRI_14_Pos))
|
(0x20 << nxp.SCB_SHPR3_PRI_14_Pos))
|
||||||
|
|
||||||
|
// turn on cycle counter
|
||||||
|
DEMCR.SetBits(DEMCR_TRCENA)
|
||||||
|
DWT_CTRL.SetBits(DWT_CTRL_CYCCNTENA)
|
||||||
|
cycleCount.Set(DWT_CYCCNT.Get())
|
||||||
|
|
||||||
// enable PIT, disable counters
|
// enable PIT, disable counters
|
||||||
nxp.PIT.MCR.Set(0)
|
nxp.PIT.MCR.Set(0)
|
||||||
for i := range nxp.PIT.TIMER {
|
for i := range nxp.PIT.TIMER {
|
||||||
|
@ -60,26 +80,32 @@ func initSysTick() {
|
||||||
pitTimeout.Enable()
|
pitTimeout.Enable()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func initRTC() {
|
||||||
|
if !nxp.SNVS.LPCR.HasBits(nxp.SNVS_LPCR_SRTC_ENV) {
|
||||||
|
// if SRTC isn't running, start it with default Jan 1, 2019
|
||||||
|
nxp.SNVS.LPSRTCLR.Set(uint32((0x5c2aad80 << 15) & 0xFFFFFFFF))
|
||||||
|
nxp.SNVS.LPSRTCMR.Set(uint32(0x5c2aad80 >> 17))
|
||||||
|
nxp.SNVS.LPCR.SetBits(nxp.SNVS_LPCR_SRTC_ENV)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//go:export SysTick_Handler
|
//go:export SysTick_Handler
|
||||||
func tick() {
|
func tick() {
|
||||||
tickCount.Set(tickCount.Get() + 1)
|
tickCount.Set(tickCount.Get() + 1)
|
||||||
|
cycleCount.Set(DWT_CYCCNT.Get())
|
||||||
}
|
}
|
||||||
|
|
||||||
func ticks() timeUnit {
|
func ticks() timeUnit {
|
||||||
mask := arm.DisableInterrupts()
|
mask := arm.DisableInterrupts()
|
||||||
curr := arm.SYST.SYST_CVR.Get()
|
|
||||||
tick := tickCount.Get()
|
tick := tickCount.Get()
|
||||||
pend := nxp.SystemControl.ICSR.HasBits(nxp.SCB_ICSR_PENDSTSET_Msk)
|
cycs := cycleCount.Get()
|
||||||
|
curr := DWT_CYCCNT.Get()
|
||||||
arm.EnableInterrupts(mask)
|
arm.EnableInterrupts(mask)
|
||||||
mics := timeUnit(tick * 1000)
|
frac := uint64((curr-cycs)*0xFFFFFFFF/cyclesPerMicro) >> 32
|
||||||
// if the systick counter was about to reset and ICSR indicates a pending
|
if frac > 1000 {
|
||||||
// SysTick IRQ, increment count
|
frac = 1000
|
||||||
if pend && (curr > 50) {
|
|
||||||
mics += 1000
|
|
||||||
} else {
|
|
||||||
mics += timeUnit((lastCycle - curr) * microsPerCycle)
|
|
||||||
}
|
}
|
||||||
return mics
|
return timeUnit(1000*tick + frac)
|
||||||
}
|
}
|
||||||
|
|
||||||
func sleepTicks(duration timeUnit) {
|
func sleepTicks(duration timeUnit) {
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче