github.com/usbarmory/tamago@v0.0.0-20240508072735-8612bbe1e454/arm/timer.go (about) 1 // ARM processor support 2 // https://github.com/usbarmory/tamago 3 // 4 // Copyright (c) WithSecure Corporation 5 // https://foundry.withsecure.com 6 // 7 // Use of this source code is governed by the license 8 // that can be found in the LICENSE file. 9 10 package arm 11 12 import ( 13 "github.com/usbarmory/tamago/internal/reg" 14 ) 15 16 // ARM timer register constants 17 const ( 18 // p2402, Table D5-1, ARMv7 Architecture Reference Manual 19 CNTCR = 0 20 // base frequency 21 CNTFID0 = 0x20 22 23 // p2410, D5.7.2 CNTCR, Counter Control Register, ARMv7 Architecture 24 // Reference Manual 25 // 26 // frequency = CNTFID0/CNTFID2 27 CNTCR_FCREQ2 = 10 28 // frequency = CNTFID0/CNTFID1 29 CNTCR_FCREQ1 = 9 30 // frequency = CNTFID0 31 CNTCR_FCREQ0 = 8 32 CNTCR_HDBG = 1 33 CNTCR_EN = 0 34 35 CNTKCTL_PL0PCTEN = 0 36 37 // nanoseconds 38 refFreq int64 = 1000000000 39 ) 40 41 // defined in timer_arm.s 42 func read_gtc() int64 43 func read_cntfrq() int32 44 func write_cntfrq(freq int32) 45 func write_cntkctl(val uint32) 46 func read_cntpct() int64 47 func write_cntptval(val int32, enable bool) 48 49 // Busyloop spins the processor for busy waiting purposes, taking a counter 50 // value for the number of loops. 51 func Busyloop(count int32) 52 53 // InitGlobalTimers initializes ARM Cortex-A9 timers. 54 func (cpu *CPU) InitGlobalTimers() { 55 cpu.TimerFn = read_gtc 56 cpu.TimerMultiplier = 10 57 } 58 59 // InitGenericTimers initializes ARM Cortex-A7 timers. 60 func (cpu *CPU) InitGenericTimers(base uint32, freq int32) { 61 var timerFreq int64 62 63 if freq != 0 && cpu.Secure() { 64 // set base frequency 65 write_cntfrq(freq) 66 67 if base != 0 { 68 reg.Write(base+CNTFID0, uint32(freq)) 69 70 // set system counter to base frequency 71 reg.Set(base+CNTCR, CNTCR_FCREQ0) 72 // stop system counter on debug 73 reg.Set(base+CNTCR, CNTCR_HDBG) 74 // start system counter 75 reg.Set(base+CNTCR, CNTCR_EN) 76 } 77 78 // grant PL0 access 79 write_cntkctl(1 << CNTKCTL_PL0PCTEN) 80 } 81 82 timerFreq = int64(read_cntfrq()) 83 84 cpu.TimerMultiplier = int64(refFreq / timerFreq) 85 cpu.TimerFn = read_cntpct 86 } 87 88 // SetTimer sets the timer to the argument nanoseconds value. 89 func (cpu *CPU) SetTimer(t int64) { 90 if cpu.TimerFn == nil || cpu.TimerMultiplier == 0 { 91 return 92 } 93 94 cpu.TimerOffset = t - int64(cpu.TimerFn()*cpu.TimerMultiplier) 95 } 96 97 // SetDownCounter sets a physical countdown timer. 98 func (cpu *CPU) SetDownCounter(t int32, enable bool) { 99 write_cntptval(t, enable) 100 }