github.com/usbarmory/tamago@v0.0.0-20240508072735-8612bbe1e454/internal/reg/reg32.go (about) 1 // https://github.com/usbarmory/tamago 2 // 3 // Copyright (c) WithSecure Corporation 4 // https://foundry.withsecure.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` as supported by the 13 // TamaGo framework for bare metal Go on ARM/RISC-V SoCs, see 14 // https://github.com/usbarmory/tamago. 15 package reg 16 17 import ( 18 "runtime" 19 "sync/atomic" 20 "time" 21 "unsafe" 22 ) 23 24 func IsSet(addr uint32, pos int) bool { 25 reg := (*uint32)(unsafe.Pointer(uintptr(addr))) 26 r := atomic.LoadUint32(reg) 27 28 return (int(r) >> pos) & 1 == 1 29 } 30 31 func Get(addr uint32, pos int, mask int) uint32 { 32 reg := (*uint32)(unsafe.Pointer(uintptr(addr))) 33 r := atomic.LoadUint32(reg) 34 35 return uint32((int(r) >> pos) & mask) 36 } 37 38 func Set(addr uint32, pos int) { 39 reg := (*uint32)(unsafe.Pointer(uintptr(addr))) 40 41 r := atomic.LoadUint32(reg) 42 r |= (1 << pos) 43 44 atomic.StoreUint32(reg, r) 45 } 46 47 func Clear(addr uint32, pos int) { 48 reg := (*uint32)(unsafe.Pointer(uintptr(addr))) 49 50 r := atomic.LoadUint32(reg) 51 r &= ^(1 << pos) 52 53 atomic.StoreUint32(reg, r) 54 } 55 56 func SetTo(addr uint32, pos int, val bool) { 57 if val { 58 Set(addr, pos) 59 } else { 60 Clear(addr, pos) 61 } 62 } 63 64 func SetN(addr uint32, pos int, mask int, val uint32) { 65 reg := (*uint32)(unsafe.Pointer(uintptr(addr))) 66 67 r := atomic.LoadUint32(reg) 68 r = (r & (^(uint32(mask) << pos))) | (val << pos) 69 70 atomic.StoreUint32(reg, r) 71 } 72 73 func ClearN(addr uint32, pos int, mask int) { 74 reg := (*uint32)(unsafe.Pointer(uintptr(addr))) 75 76 r := atomic.LoadUint32(reg) 77 r &= ^(uint32(mask) << pos) 78 79 atomic.StoreUint32(reg, r) 80 } 81 82 // defined in reg32_*.s 83 func Move(dst uint32, src uint32) 84 85 func Read(addr uint32) uint32 { 86 reg := (*uint32)(unsafe.Pointer(uintptr(addr))) 87 return atomic.LoadUint32(reg) 88 } 89 90 func Write(addr uint32, val uint32) { 91 reg := (*uint32)(unsafe.Pointer(uintptr(addr))) 92 atomic.StoreUint32(reg, val) 93 } 94 95 func WriteBack(addr uint32) { 96 reg := (*uint32)(unsafe.Pointer(uintptr(addr))) 97 98 r := atomic.LoadUint32(reg) 99 r |= r 100 101 atomic.StoreUint32(reg, r) 102 } 103 104 func Or(addr uint32, val uint32) { 105 reg := (*uint32)(unsafe.Pointer(uintptr(addr))) 106 107 r := atomic.LoadUint32(reg) 108 r |= val 109 110 atomic.StoreUint32(reg, r) 111 } 112 113 // Wait waits for a specific register bit to match a value. This function 114 // cannot be used before runtime initialization with `GOOS=tamago`. 115 func Wait(addr uint32, pos int, mask int, val uint32) { 116 for Get(addr, pos, mask) != val { 117 // tamago is single-threaded, give other goroutines a chance 118 runtime.Gosched() 119 } 120 } 121 122 // WaitFor waits, until a timeout expires, for a specific register bit to match 123 // a value. The return boolean indicates whether the wait condition was checked 124 // (true) or if it timed out (false). This function cannot be used before 125 // runtime initialization. 126 func WaitFor(timeout time.Duration, addr uint32, pos int, mask int, val uint32) bool { 127 start := time.Now() 128 129 for Get(addr, pos, mask) != val { 130 // tamago is single-threaded, give other goroutines a chance 131 runtime.Gosched() 132 133 if time.Since(start) >= timeout { 134 return false 135 } 136 } 137 138 return true 139 } 140 141 // WaitSignal waits, until a channel is closed, for a specific register bit to 142 // match a value. The return boolean indicates whether the wait condition was 143 // checked (true) or cancelled (false). This function cannot be used before 144 // runtime initialization. 145 func WaitSignal(exit chan struct{}, addr uint32, pos int, mask int, val uint32) bool { 146 for Get(addr, pos, mask) != val { 147 // tamago is single-threaded, give other goroutines a chance 148 runtime.Gosched() 149 150 select { 151 case <-exit: 152 return false 153 default: 154 } 155 } 156 157 return true 158 }