I am attempting my first SPI driver for the TMS320F2812. I
went into this hoping for the simplest possible driver (no
interrupts).
I want my SPI port to drive two MicroChip MCP23S17 16-bit
bi-directional port expanders. They require the master to
send commands of multiple bytes during a single chip select
cycle. Also, since there is more than one device I must
drive their chip select lines manually.
The way I read the SPI reference guide, there is one level
of buffering between the user and the shift register:
+--------+
|SPITXBUF|
+--------+
||
\/ MISO
+--------+<---------
|SPIDAT | MOSI
+--------+--------->
||
\/
+--------+
|SPIRXBUF|
+--------+
so I can stuff two bytes into the hardware without worrying
about Tx overflow. But my slaves mandate longer strings than
that. It seems to me I must monitor the status of the SPI
hardware to determine when it is safe to stuff another byte.
I found two bits in the SPI status register:
- SPIST.6: SPI INT FLAG, &
- SPIST.5: SPI TX BUF FULL FLAG
The TX BUF FULL FLAG should tell me when it is safe to load
more data.
Next, I need to know when it is time to bring my chip select
on the slave device false, which can only be after all the
bytes I have sent it have been shifted out. The INT FLAG is
only a partial solution to this problem, as it will go true
for the first byte and remain set thereafter, unless I reset
it immediately after each byte clears the shift register.
Initially, the only complete solution I could see was to
enable the SPI interrupt, increment a counter every time I
stuff a byte into the port and have the SPI ISR decrement
that counter every time it clears the SPI INT FLAG. So at
the main level I would send all my bytes out, and watch that
counter until it counted down to 0, at which point I could
bring chip select high.
An earlier poster was referred to a TI App Note, SPRU059,
which I have spent several days taking apart. It is a
dedicated SPI E²PROM driver using a finite state machine,
and does not use SPI interrupts, but appears to poll the SPI
INT FLAG, inside another ISR driven at 10 kHz by a timer
inside the event manager.
This is a fairly sophisticated solution, but the concepts of
SPI and E²PROM are hopelessly entangled, so I don't see an
easy way to use it for my port expanders.
Are there any other SPI driver examples out there?