github.com/f-secure-foundry/tamago@v0.0.0-20220307101044-d73fcdd7f11b/internal/reg/reg32.go (about) 1 // https://github.com/f-secure-foundry/tamago 2 // 3 // Copyright (c) F-Secure Corporation 4 // https://foundry.f-secure.com 5 // 6 // Use of this source code is governed by the license 7 // that can be found in the LICENSE file. 8 9 // Package reg provides primitives for retrieving and modifying hardware 10 // registers. 11 // 12 // This package is only meant to be used with `GOOS=tamago GOARCH=arm` as 13 // supported by the TamaGo framework for bare metal Go on ARM SoCs, see 14 // https://github.com/f-secure-foundry/tamago. 15 package reg 16 17 import ( 18 "runtime" 19 "sync/atomic" 20 "time" 21 "unsafe" 22 ) 23 24 func Get(addr uint32, pos int, mask int) uint32 { 25 reg := (*uint32)(unsafe.Pointer(uintptr(addr))) 26 r := atomic.LoadUint32(reg) 27 28 return uint32((int(r) >> pos) & mask) 29 } 30 31 func Set(addr uint32, pos int) { 32 reg := (*uint32)(unsafe.Pointer(uintptr(addr))) 33 34 r := atomic.LoadUint32(reg) 35 r |= (1 << pos) 36 37 atomic.StoreUint32(reg, r) 38 } 39 40 func Clear(addr uint32, pos int) { 41 reg := (*uint32)(unsafe.Pointer(uintptr(addr))) 42 43 r := atomic.LoadUint32(reg) 44 r &= ^(1 << pos) 45 46 atomic.StoreUint32(reg, r) 47 } 48 49 func SetN(addr uint32, pos int, mask int, val uint32) { 50 reg := (*uint32)(unsafe.Pointer(uintptr(addr))) 51 52 r := atomic.LoadUint32(reg) 53 r = (r & (^(uint32(mask) << pos))) | (val << pos) 54 55 atomic.StoreUint32(reg, r) 56 } 57 58 func ClearN(addr uint32, pos int, mask int) { 59 reg := (*uint32)(unsafe.Pointer(uintptr(addr))) 60 61 r := atomic.LoadUint32(reg) 62 r &= ^(uint32(mask) << pos) 63 64 atomic.StoreUint32(reg, r) 65 } 66 67 // defined in reg32.s 68 func Move(dst uint32, src uint32) 69 70 func Read(addr uint32) uint32 { 71 reg := (*uint32)(unsafe.Pointer(uintptr(addr))) 72 return atomic.LoadUint32(reg) 73 } 74 75 func Write(addr uint32, val uint32) { 76 reg := (*uint32)(unsafe.Pointer(uintptr(addr))) 77 atomic.StoreUint32(reg, val) 78 } 79 80 func WriteBack(addr uint32) { 81 reg := (*uint32)(unsafe.Pointer(uintptr(addr))) 82 83 r := atomic.LoadUint32(reg) 84 r |= r 85 86 atomic.StoreUint32(reg, r) 87 } 88 89 func Or(addr uint32, val uint32) { 90 reg := (*uint32)(unsafe.Pointer(uintptr(addr))) 91 92 r := atomic.LoadUint32(reg) 93 r |= val 94 95 atomic.StoreUint32(reg, r) 96 } 97 98 // Wait waits for a specific register bit to match a value. This function 99 // cannot be used before runtime initialization with `GOOS=tamago`. 100 func Wait(addr uint32, pos int, mask int, val uint32) { 101 for Get(addr, pos, mask) != val { 102 // tamago is single-threaded, give other goroutines a chance 103 runtime.Gosched() 104 } 105 } 106 107 // WaitFor waits, until a timeout expires, for a specific register bit to match 108 // a value. The return boolean indicates whether the wait condition was checked 109 // (true) or if it timed out (false). This function cannot be used before 110 // runtime initialization. 111 func WaitFor(timeout time.Duration, addr uint32, pos int, mask int, val uint32) bool { 112 start := time.Now() 113 114 for Get(addr, pos, mask) != val { 115 // tamago is single-threaded, give other goroutines a chance 116 runtime.Gosched() 117 118 if time.Since(start) >= timeout { 119 return false 120 } 121 } 122 123 return true 124 } 125 126 // WaitSignal waits, until a channel is closed, for a specific register bit to 127 // match a value. The return boolean indicates whether the wait condition was 128 // checked (true) or cancelled (false). This function cannot be used before 129 // runtime initialization. 130 func WaitSignal(done chan bool, addr uint32, pos int, mask int, val uint32) bool { 131 for Get(addr, pos, mask) != val { 132 // tamago is single-threaded, give other goroutines a chance 133 runtime.Gosched() 134 135 select { 136 case <-done: 137 return false 138 default: 139 } 140 } 141 142 return true 143 }