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  }