|
|
@ -47,9 +47,6 @@ type SPI struct { |
|
|
|
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
|
|
|
|
// 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.
|
|
|
@ -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.
|
|
|
|
func (spi SPI) Transfer(w byte) (byte, error) { |
|
|
|
var deadline = ticks() + _SPITimeout |
|
|
|
for !spi.isWritable() { |
|
|
|
if ticks() > deadline { |
|
|
|
return 0, ErrSPITimeout |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
spi.Bus.SSPDR.Set(uint32(w)) |
|
|
|
|
|
|
|
for !spi.isReadable() { |
|
|
|
if ticks() > deadline { |
|
|
|
return 0, ErrSPITimeout |
|
|
|
} |
|
|
|
} |
|
|
|
return uint8(spi.Bus.SSPDR.Get()), nil |
|
|
|
} |
|
|
@ -298,15 +288,11 @@ func (spi SPI) isBusy() bool { |
|
|
|
|
|
|
|
// tx writes buffer to SPI ignoring Rx.
|
|
|
|
func (spi SPI) tx(tx []byte) error { |
|
|
|
var deadline = ticks() + _SPITimeout |
|
|
|
// 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
|
|
|
|
// push-on-full, but continues shifting. Safe if SSPIMSC_RORIM is not set.
|
|
|
|
for i := range tx { |
|
|
|
for !spi.isWritable() { |
|
|
|
if ticks() > deadline { |
|
|
|
return ErrSPITimeout |
|
|
|
} |
|
|
|
} |
|
|
|
spi.Bus.SSPDR.Set(uint32(tx[i])) |
|
|
|
} |
|
|
@ -316,9 +302,6 @@ func (spi SPI) tx(tx []byte) error { |
|
|
|
spi.Bus.SSPDR.Get() |
|
|
|
} |
|
|
|
for spi.isBusy() { |
|
|
|
if ticks() > deadline { |
|
|
|
return ErrSPITimeout |
|
|
|
} |
|
|
|
} |
|
|
|
for spi.isReadable() { |
|
|
|
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,
|
|
|
|
// e.g. SD cards expect 0xff
|
|
|
|
func (spi SPI) rx(rx []byte, txrepeat byte) error { |
|
|
|
var deadline = ticks() + _SPITimeout |
|
|
|
plen := len(rx) |
|
|
|
const fifoDepth = 8 // see txrx
|
|
|
|
var rxleft, txleft = plen, plen |
|
|
@ -345,10 +327,7 @@ func (spi SPI) rx(rx []byte, txrepeat byte) error { |
|
|
|
if rxleft != 0 && spi.isReadable() { |
|
|
|
rx[plen-rxleft] = uint8(spi.Bus.SSPDR.Get()) |
|
|
|
rxleft-- |
|
|
|
continue // if reading succesfully in rx there is no need to check deadline.
|
|
|
|
} |
|
|
|
if ticks() > deadline { |
|
|
|
return ErrSPITimeout |
|
|
|
continue |
|
|
|
} |
|
|
|
} |
|
|
|
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.
|
|
|
|
// 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 { |
|
|
|
var deadline = ticks() + _SPITimeout |
|
|
|
plen := len(tx) |
|
|
|
if plen != len(rx) { |
|
|
|
return ErrTxInvalidSliceSize |
|
|
@ -366,7 +344,7 @@ func (spi SPI) txrx(tx, rx []byte) error { |
|
|
|
// else FIFO will overflow if this code is heavily interrupted.
|
|
|
|
const fifoDepth = 8 |
|
|
|
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 { |
|
|
|
spi.Bus.SSPDR.Set(uint32(tx[plen-txleft])) |
|
|
|
txleft-- |
|
|
|