Merge pull request #29 from Drahoslav7/perf/gpio-write

Perf/gpio - faster write and toggle
This commit is contained in:
Stian Eikeland 2018-10-09 11:54:54 +02:00 committed by GitHub
commit 2c2ef096f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 91 additions and 9 deletions

27
rpio.go
View File

@ -284,19 +284,19 @@ func PinMode(pin Pin, mode Mode) {
func WritePin(pin Pin, state State) {
p := uint8(pin)
// Clear register, 10 / 11 depending on bank
// Set register, 7 / 8 depending on bank
clearReg := p/32 + 10
// Clear register, 10 / 11 depending on bank
setReg := p/32 + 7
clearReg := p/32 + 10
memlock.Lock()
defer memlock.Unlock()
if state == Low {
gpioMem[clearReg] = 1 << (p & 31)
} else {
gpioMem[setReg] = 1 << (p & 31)
}
memlock.Unlock() // not deferring saves ~600ns
}
// Read the state of a pin
@ -312,14 +312,23 @@ func ReadPin(pin Pin) State {
}
// Toggle a pin state (high -> low -> high)
// TODO: probably possible to do this much faster without read
func TogglePin(pin Pin) {
switch ReadPin(pin) {
case Low:
pin.High()
case High:
pin.Low()
p := uint8(pin)
setReg := p/32 + 7
clearReg := p/32 + 10
levelReg := p/32 + 13
bit := uint32(1 << (p & 31))
memlock.Lock()
if (gpioMem[levelReg] & bit) != 0 {
gpioMem[clearReg] = bit
} else {
gpioMem[setReg] = bit
}
memlock.Unlock()
}
// Enable edge event detection on pin.

View File

@ -117,4 +117,77 @@ func TestEvent(t *testing.T) {
}
})
}
func BenchmarkGpio(b *testing.B) {
src := Pin(3)
src.Mode(Output)
src.Low()
pin := Pin(2)
pin.Mode(Input)
pin.PullDown()
oldWrite := func(pin Pin, state State) {
p := uint8(pin)
setReg := p/32 + 7
clearReg := p/32 + 10
memlock.Lock()
defer memlock.Unlock()
if state == Low {
gpioMem[clearReg] = 1 << (p & 31)
} else {
gpioMem[setReg] = 1 << (p & 31)
}
}
oldToggle := func(pin Pin) {
switch ReadPin(pin) {
case Low:
oldWrite(pin, High)
case High:
oldWrite(pin, Low)
}
}
b.Run("write", func(b *testing.B) {
b.Run("old", func(b *testing.B) {
for i := 0; i < b.N; i++ {
if i%2 == 0 {
oldWrite(src, High)
} else {
oldWrite(src, Low)
}
}
})
b.Run("new", func(b *testing.B) {
for i := 0; i < b.N; i++ {
if i%2 == 0 {
WritePin(src, High)
} else {
WritePin(src, Low)
}
}
})
})
b.Run("toggle", func(b *testing.B) {
b.Run("old", func(b *testing.B) {
for i := 0; i < b.N; i++ {
oldToggle(src)
}
})
b.Run("new", func(b *testing.B) {
for i := 0; i < b.N; i++ {
TogglePin(src)
}
})
})
}