rp2040: remove SPI deadline
Removing it improves SPI performance by about 20% for me (updating the display of a Gopher Badge).
Этот коммит содержится в:
родитель
8badf79af9
коммит
6eda52a289
1 изменённых файлов: 2 добавлений и 24 удалений
|
@ -47,9 +47,6 @@ type SPI struct {
|
||||||
Bus *rp.SPI0_Type
|
Bus *rp.SPI0_Type
|
||||||
}
|
}
|
||||||
|
|
||||||
// time to wait on a transaction before dropping. Unit in Microseconds for compatibility with ticks().
|
|
||||||
const _SPITimeout = 10 * 1000 // 10 ms
|
|
||||||
|
|
||||||
// Tx handles read/write operation for SPI interface. Since SPI is a syncronous write/read
|
// Tx handles read/write operation for SPI interface. Since SPI is a syncronous write/read
|
||||||
// interface, there must always be the same number of bytes written as bytes read.
|
// interface, there must always be the same number of bytes written as bytes read.
|
||||||
// The Tx method knows about this, and offers a few different ways of calling it.
|
// The Tx method knows about this, and offers a few different ways of calling it.
|
||||||
|
@ -95,19 +92,12 @@ func (spi SPI) Tx(w, r []byte) (err error) {
|
||||||
|
|
||||||
// Write a single byte and read a single byte from TX/RX FIFO.
|
// Write a single byte and read a single byte from TX/RX FIFO.
|
||||||
func (spi SPI) Transfer(w byte) (byte, error) {
|
func (spi SPI) Transfer(w byte) (byte, error) {
|
||||||
var deadline = ticks() + _SPITimeout
|
|
||||||
for !spi.isWritable() {
|
for !spi.isWritable() {
|
||||||
if ticks() > deadline {
|
|
||||||
return 0, ErrSPITimeout
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
spi.Bus.SSPDR.Set(uint32(w))
|
spi.Bus.SSPDR.Set(uint32(w))
|
||||||
|
|
||||||
for !spi.isReadable() {
|
for !spi.isReadable() {
|
||||||
if ticks() > deadline {
|
|
||||||
return 0, ErrSPITimeout
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return uint8(spi.Bus.SSPDR.Get()), nil
|
return uint8(spi.Bus.SSPDR.Get()), nil
|
||||||
}
|
}
|
||||||
|
@ -298,15 +288,11 @@ func (spi SPI) isBusy() bool {
|
||||||
|
|
||||||
// tx writes buffer to SPI ignoring Rx.
|
// tx writes buffer to SPI ignoring Rx.
|
||||||
func (spi SPI) tx(tx []byte) error {
|
func (spi SPI) tx(tx []byte) error {
|
||||||
var deadline = ticks() + _SPITimeout
|
|
||||||
// Write to TX FIFO whilst ignoring RX, then clean up afterward. When RX
|
// Write to TX FIFO whilst ignoring RX, then clean up afterward. When RX
|
||||||
// is full, PL022 inhibits RX pushes, and sets a sticky flag on
|
// is full, PL022 inhibits RX pushes, and sets a sticky flag on
|
||||||
// push-on-full, but continues shifting. Safe if SSPIMSC_RORIM is not set.
|
// push-on-full, but continues shifting. Safe if SSPIMSC_RORIM is not set.
|
||||||
for i := range tx {
|
for i := range tx {
|
||||||
for !spi.isWritable() {
|
for !spi.isWritable() {
|
||||||
if ticks() > deadline {
|
|
||||||
return ErrSPITimeout
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
spi.Bus.SSPDR.Set(uint32(tx[i]))
|
spi.Bus.SSPDR.Set(uint32(tx[i]))
|
||||||
}
|
}
|
||||||
|
@ -316,9 +302,6 @@ func (spi SPI) tx(tx []byte) error {
|
||||||
spi.Bus.SSPDR.Get()
|
spi.Bus.SSPDR.Get()
|
||||||
}
|
}
|
||||||
for spi.isBusy() {
|
for spi.isBusy() {
|
||||||
if ticks() > deadline {
|
|
||||||
return ErrSPITimeout
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for spi.isReadable() {
|
for spi.isReadable() {
|
||||||
spi.Bus.SSPDR.Get()
|
spi.Bus.SSPDR.Get()
|
||||||
|
@ -333,7 +316,6 @@ func (spi SPI) tx(tx []byte) error {
|
||||||
// Generally this can be 0, but some devices require a specific value here,
|
// Generally this can be 0, but some devices require a specific value here,
|
||||||
// e.g. SD cards expect 0xff
|
// e.g. SD cards expect 0xff
|
||||||
func (spi SPI) rx(rx []byte, txrepeat byte) error {
|
func (spi SPI) rx(rx []byte, txrepeat byte) error {
|
||||||
var deadline = ticks() + _SPITimeout
|
|
||||||
plen := len(rx)
|
plen := len(rx)
|
||||||
const fifoDepth = 8 // see txrx
|
const fifoDepth = 8 // see txrx
|
||||||
var rxleft, txleft = plen, plen
|
var rxleft, txleft = plen, plen
|
||||||
|
@ -345,10 +327,7 @@ func (spi SPI) rx(rx []byte, txrepeat byte) error {
|
||||||
if rxleft != 0 && spi.isReadable() {
|
if rxleft != 0 && spi.isReadable() {
|
||||||
rx[plen-rxleft] = uint8(spi.Bus.SSPDR.Get())
|
rx[plen-rxleft] = uint8(spi.Bus.SSPDR.Get())
|
||||||
rxleft--
|
rxleft--
|
||||||
continue // if reading succesfully in rx there is no need to check deadline.
|
continue
|
||||||
}
|
|
||||||
if ticks() > deadline {
|
|
||||||
return ErrSPITimeout
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -357,7 +336,6 @@ func (spi SPI) rx(rx []byte, txrepeat byte) error {
|
||||||
// Write len bytes from src to SPI. Simultaneously read len bytes from SPI to dst.
|
// Write len bytes from src to SPI. Simultaneously read len bytes from SPI to dst.
|
||||||
// Note this function is guaranteed to exit in a known amount of time (bits sent * time per bit)
|
// Note this function is guaranteed to exit in a known amount of time (bits sent * time per bit)
|
||||||
func (spi SPI) txrx(tx, rx []byte) error {
|
func (spi SPI) txrx(tx, rx []byte) error {
|
||||||
var deadline = ticks() + _SPITimeout
|
|
||||||
plen := len(tx)
|
plen := len(tx)
|
||||||
if plen != len(rx) {
|
if plen != len(rx) {
|
||||||
return ErrTxInvalidSliceSize
|
return ErrTxInvalidSliceSize
|
||||||
|
@ -366,7 +344,7 @@ func (spi SPI) txrx(tx, rx []byte) error {
|
||||||
// else FIFO will overflow if this code is heavily interrupted.
|
// else FIFO will overflow if this code is heavily interrupted.
|
||||||
const fifoDepth = 8
|
const fifoDepth = 8
|
||||||
var rxleft, txleft = plen, plen
|
var rxleft, txleft = plen, plen
|
||||||
for (txleft != 0 || rxleft != 0) && ticks() <= deadline {
|
for txleft != 0 || rxleft != 0 {
|
||||||
if txleft != 0 && spi.isWritable() && rxleft < txleft+fifoDepth {
|
if txleft != 0 && spi.isWritable() && rxleft < txleft+fifoDepth {
|
||||||
spi.Bus.SSPDR.Set(uint32(tx[plen-txleft]))
|
spi.Bus.SSPDR.Set(uint32(tx[plen-txleft]))
|
||||||
txleft--
|
txleft--
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче