aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAyke van Laethem <[email protected]>2022-07-27 12:43:34 +0200
committerRon Evans <[email protected]>2022-07-27 17:22:34 +0200
commit99bd4d2c7cdc838830af75d433effaf9c762c741 (patch)
tree6b94e4bb11d7ea61c5fabab507cff422e1e3717e
parenta4b22bd125e4a8ed3230b56158c5d1426b208911 (diff)
downloadtinygo-99bd4d2c7cdc838830af75d433effaf9c762c741.tar.gz
tinygo-99bd4d2c7cdc838830af75d433effaf9c762c741.zip
esp32: optimize SPI transmit
For write-only operations (in SPI displays for example), the transmit speed is doubled with this relatively small change. In the future, we should try to use DMA instead for larger buffers. But this is already a significant improvement and will always be an improvement for small buffer sizes.
-rw-r--r--src/machine/machine_esp32.go39
1 files changed, 29 insertions, 10 deletions
diff --git a/src/machine/machine_esp32.go b/src/machine/machine_esp32.go
index 9f9960b33..dd3ddc41e 100644
--- a/src/machine/machine_esp32.go
+++ b/src/machine/machine_esp32.go
@@ -478,16 +478,35 @@ func (spi SPI) Tx(w, r []byte) error {
// Fill tx buffer.
transferWords := (*[16]volatile.Register32)(unsafe.Pointer(uintptr(unsafe.Pointer(&spi.Bus.W0))))
- var outBuf [16]uint32
- txSize := 64
- if txSize > len(w) {
- txSize = len(w)
- }
- for i := 0; i < txSize; i++ {
- outBuf[i/4] = outBuf[i/4] | uint32(w[i])<<((i%4)*8)
- }
- for i, word := range outBuf {
- transferWords[i].Set(word)
+ if len(w) >= 64 {
+ // We can fill the entire 64-byte transfer buffer with data.
+ // This loop is slightly faster than the loop below.
+ for i := 0; i < 16; i++ {
+ word := uint32(w[i*4])<<0 | uint32(w[i*4+1])<<8 | uint32(w[i*4+2])<<16 | uint32(w[i*4+3])<<24
+ transferWords[i].Set(word)
+ }
+ } else {
+ // We can't fill the entire transfer buffer, so we need to be a bit
+ // more careful.
+ // Note that parts of the transfer buffer that aren't used still
+ // need to be set to zero, otherwise we might be transferring
+ // garbage from a previous transmission if w is smaller than r.
+ for i := 0; i < 16; i++ {
+ var word uint32
+ if i*4+3 < len(w) {
+ word |= uint32(w[i*4+3]) << 24
+ }
+ if i*4+2 < len(w) {
+ word |= uint32(w[i*4+2]) << 16
+ }
+ if i*4+1 < len(w) {
+ word |= uint32(w[i*4+1]) << 8
+ }
+ if i*4+0 < len(w) {
+ word |= uint32(w[i*4+0]) << 0
+ }
+ transferWords[i].Set(word)
+ }
}
// Do the transfer.