Skip to content

Commit

Permalink
all: move Register{8,16,32} values into runtime/volatile
Browse files Browse the repository at this point in the history
This avoids duplication of code. None of the smoke tests have changed
their output.
  • Loading branch information
aykevl authored and deadprogram committed Jun 6, 2019
1 parent 66aca42 commit 9673ad3
Show file tree
Hide file tree
Showing 7 changed files with 189 additions and 236 deletions.
3 changes: 2 additions & 1 deletion src/machine/machine_atmega.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package machine

import (
"device/avr"
"runtime/volatile"
)

// Configure sets the pin to input or output.
Expand Down Expand Up @@ -34,7 +35,7 @@ func (p Pin) Get() bool {
}
}

func (p Pin) getPortMask() (*avr.Register8, uint8) {
func (p Pin) getPortMask() (*volatile.Register8, uint8) {
if p < 8 {
return avr.PORTD, 1 << uint8(p)
} else {
Expand Down
3 changes: 2 additions & 1 deletion src/machine/machine_attiny.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package machine

import (
"device/avr"
"runtime/volatile"
)

// Configure sets the pin to input or output.
Expand All @@ -15,7 +16,7 @@ func (p Pin) Configure(config PinConfig) {
}
}

func (p Pin) getPortMask() (*avr.Register8, uint8) {
func (p Pin) getPortMask() (*volatile.Register8, uint8) {
return avr.PORTB, 1 << uint8(p)
}

Expand Down
5 changes: 3 additions & 2 deletions src/machine/machine_avr.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package machine

import (
"device/avr"
"runtime/volatile"
)

type PinMode uint8
Expand All @@ -30,7 +31,7 @@ func (p Pin) Set(value bool) {
// Warning: there are no separate pin set/clear registers on the AVR. The
// returned mask is only valid as long as no other pin in the same port has been
// changed.
func (p Pin) PortMaskSet() (*avr.Register8, uint8) {
func (p Pin) PortMaskSet() (*volatile.Register8, uint8) {
port, mask := p.getPortMask()
return port, port.Get() | mask
}
Expand All @@ -41,7 +42,7 @@ func (p Pin) PortMaskSet() (*avr.Register8, uint8) {
// Warning: there are no separate pin set/clear registers on the AVR. The
// returned mask is only valid as long as no other pin in the same port has been
// changed.
func (p Pin) PortMaskClear() (*avr.Register8, uint8) {
func (p Pin) PortMaskClear() (*volatile.Register8, uint8) {
port, mask := p.getPortMask()
return port, port.Get() &^ mask
}
Expand Down
12 changes: 6 additions & 6 deletions src/machine/usb.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ package machine

import (
"bytes"
"device/sam"
"encoding/binary"
"errors"
"runtime/volatile"
)

const deviceDescriptorSize = 18
Expand Down Expand Up @@ -484,11 +484,11 @@ const (
// RoReg8 Reserved1[0x5];
// } UsbDeviceDescBank;
type usbDeviceDescBank struct {
ADDR sam.Register32
PCKSIZE sam.Register32
EXTREG sam.Register16
STATUS_BK sam.Register8
_reserved [5]sam.Register8
ADDR volatile.Register32
PCKSIZE volatile.Register32
EXTREG volatile.Register16
STATUS_BK volatile.Register8
_reserved [5]volatile.Register8
}

type usbDeviceDescriptor struct {
Expand Down
162 changes: 162 additions & 0 deletions src/runtime/volatile/register.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
package volatile

// This file defines Register{8,16,32} types, which are convenience types for
// volatile register accesses.

// Special types that causes loads/stores to be volatile (necessary for
// memory-mapped registers).
type Register8 struct {
Reg uint8
}

// Get returns the value in the register. It is the volatile equivalent of:
//
// *r.Reg
//
//go:inline
func (r *Register8) Get() uint8 {
return LoadUint8(&r.Reg)
}

// Set updates the register value. It is the volatile equivalent of:
//
// *r.Reg = value
//
//go:inline
func (r *Register8) Set(value uint8) {
StoreUint8(&r.Reg, value)
}

// SetBits reads the register, sets the given bits, and writes it back. It is
// the volatile equivalent of:
//
// r.Reg |= value
//
//go:inline
func (r *Register8) SetBits(value uint8) {
StoreUint8(&r.Reg, LoadUint8(&r.Reg)|value)
}

// ClearBits reads the register, clears the given bits, and writes it back. It
// is the volatile equivalent of:
//
// r.Reg &^= value
//
//go:inline
func (r *Register8) ClearBits(value uint8) {
StoreUint8(&r.Reg, LoadUint8(&r.Reg)&^value)
}

// HasBits reads the register and then checks to see if the passed bits are set. It
// is the volatile equivalent of:
//
// (*r.Reg & value) > 0
//
//go:inline
func (r *Register8) HasBits(value uint8) bool {
return (r.Get() & value) > 0
}

type Register16 struct {
Reg uint16
}

// Get returns the value in the register. It is the volatile equivalent of:
//
// *r.Reg
//
//go:inline
func (r *Register16) Get() uint16 {
return LoadUint16(&r.Reg)
}

// Set updates the register value. It is the volatile equivalent of:
//
// *r.Reg = value
//
//go:inline
func (r *Register16) Set(value uint16) {
StoreUint16(&r.Reg, value)
}

// SetBits reads the register, sets the given bits, and writes it back. It is
// the volatile equivalent of:
//
// r.Reg |= value
//
//go:inline
func (r *Register16) SetBits(value uint16) {
StoreUint16(&r.Reg, LoadUint16(&r.Reg)|value)
}

// ClearBits reads the register, clears the given bits, and writes it back. It
// is the volatile equivalent of:
//
// r.Reg &^= value
//
//go:inline
func (r *Register16) ClearBits(value uint16) {
StoreUint16(&r.Reg, LoadUint16(&r.Reg)&^value)
}

// HasBits reads the register and then checks to see if the passed bits are set. It
// is the volatile equivalent of:
//
// (*r.Reg & value) > 0
//
//go:inline
func (r *Register16) HasBits(value uint16) bool {
return (r.Get() & value) > 0
}

type Register32 struct {
Reg uint32
}

// Get returns the value in the register. It is the volatile equivalent of:
//
// *r.Reg
//
//go:inline
func (r *Register32) Get() uint32 {
return LoadUint32(&r.Reg)
}

// Set updates the register value. It is the volatile equivalent of:
//
// *r.Reg = value
//
//go:inline
func (r *Register32) Set(value uint32) {
StoreUint32(&r.Reg, value)
}

// SetBits reads the register, sets the given bits, and writes it back. It is
// the volatile equivalent of:
//
// r.Reg |= value
//
//go:inline
func (r *Register32) SetBits(value uint32) {
StoreUint32(&r.Reg, LoadUint32(&r.Reg)|value)
}

// ClearBits reads the register, clears the given bits, and writes it back. It
// is the volatile equivalent of:
//
// r.Reg &^= value
//
//go:inline
func (r *Register32) ClearBits(value uint32) {
StoreUint32(&r.Reg, LoadUint32(&r.Reg)&^value)
}

// HasBits reads the register and then checks to see if the passed bits are set. It
// is the volatile equivalent of:
//
// (*r.Reg & value) > 0
//
//go:inline
func (r *Register32) HasBits(value uint32) bool {
return (r.Get() & value) > 0
}
56 changes: 1 addition & 55 deletions tools/gen-device-avr.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,60 +156,6 @@ def writeGo(outdir, device):
"unsafe"
)
// Special type that causes loads/stores to be volatile (necessary for
// memory-mapped registers).
type Register8 struct {{
Reg uint8
}}
// Get returns the value in the register. It is the volatile equivalent of:
//
// *r.Reg
//
//go:inline
func (r *Register8) Get() uint8 {{
return volatile.LoadUint8(&r.Reg)
}}
// Set updates the register value. It is the volatile equivalent of:
//
// *r.Reg = value
//
//go:inline
func (r *Register8) Set(value uint8) {{
volatile.StoreUint8(&r.Reg, value)
}}
// SetBits reads the register, sets the given bits, and writes it back. It is
// the volatile equivalent of:
//
// r.Reg |= value
//
//go:inline
func (r *Register8) SetBits(value uint8) {{
volatile.StoreUint8(&r.Reg, volatile.LoadUint8(&r.Reg) | value)
}}
// ClearBits reads the register, clears the given bits, and writes it back. It
// is the volatile equivalent of:
//
// r.Reg &^= value
//
//go:inline
func (r *Register8) ClearBits(value uint8) {{
volatile.StoreUint8(&r.Reg, volatile.LoadUint8(&r.Reg) &^ value)
}}
// HasBits reads the register and then checks to see if the passed bits are set. It
// is the volatile equivalent of:
//
// (*r.Reg & value) > 0
//
//go:inline
func (r *Register8) HasBits(value uint8) bool {{
return (r.Get() & value) > 0
}}
// Some information about this device.
const (
DEVICE = "{name}"
Expand All @@ -231,7 +177,7 @@ def writeGo(outdir, device):
out.write('\n\t// {description}\n'.format(**peripheral))
for register in peripheral['registers']:
for variant in register['variants']:
out.write('\t{name} = (*Register8)(unsafe.Pointer(uintptr(0x{address:x})))\n'.format(**variant))
out.write('\t{name} = (*volatile.Register8)(unsafe.Pointer(uintptr(0x{address:x})))\n'.format(**variant))
out.write(')\n')

for peripheral in device.peripherals:
Expand Down
Loading

0 comments on commit 9673ad3

Please sign in to comment.