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