Sysctl SPI rework
what's happening
- we can bump the clock to 4MHz, 10x faster than before. this also makes transmission more reliable
- the response time to SPI commands needs to be pretty tight in the firmware, and then we can get rid of massive delays in the driver
- to negotiate this support, i introduce API version 2 which is derived from the firmware build date
- when API >= 2 is detected, the delays are strongly reduced
- to make pocket reform LPC fw SPI responsive enough, i put it on a 5ms timer interval that checks the SPI inbox, returns if empty, otherwise reads 4 bytes
- got rid of the unnecessary "parser"
- also updating the battery info for SPI more often now so we can do higher fidelity monitoring over sysfs
- matching LPC driver MR: reform-tools!127 (merged)
some SPI theory
- in SPI, write/read is always one simultaneous transaction, which means that, for example, 8 bytes can be written and read at the same time. but:
- there are FIFOs that buffer reading and writing in the ARM PrimeCell SPI block
- this isn't always practical for request/response patterns
- the pico-sdk read/write API is designed so that you do half-duplex:
- when you write() from the pico side, it'll read and discard the same number of bytes from the host
- when you read() from the pico side, it'll send the same number of dummy bytes (i.e. 0xff, you can specify)
- the linux spi_read()/spi_write() are meant for full duplex, but use the FIFO buffers.
- linux spi_write() sends what you pass in to the client, but doesn't discard the (dummy) response
- so if you use the normal read() from the pico, you have to do a useless spi_read() on the linux side to consume those bytes that are now in the read buffer from the previous write()
- if you write from linux using spi_write(), and then read that on the rp2040 using spi_read_blocking(), you don't need to explicitly write something back, because that's already part of the read in the pico API
- and you need to consume this dummy response on the linux side, it doesn't get automatically discarded
- in the original classic lpc11u24 firmware, to read the command from the host, i just manually did:
uint8_t rx = LPC_SSP0->DR;
(not filling the write buffer at the same time!) - to stay compatible i need to do the same on the rp2040/rp2350 and can't use spi_read_blocking, so i'll do
rx = (uint8_t)spi_get_hw(spi)->dr;
(equivalent). this also avoids an extra spi_read(with len=4) call on the linux side before reading the actual response (with len=8).
Edited by minute