Please refer my previous page to understand Data Transmission via SPI.
The following block diagram uses a simple model to describe the hardware mechanism of SPI Host Controller with RX/TX FIFO, registers accessed by a program, and 4 SPI wires connected to a SPI device. This diagram skips the shift register in SPI Host Controller. It also skips the details hardware components of the SPI device.
SPI 4 Wires.
SPI has 4 wires, CS, CLK, MOSI, and MISO. Please refer the wiki page, SPI Bus.
Two FIFOs.
TX FIFO transmits data to a SPI device (e.g., flash part) via MOSI. When data are transmitted, CLK is also enabled. Therefore RX FIFO might receive dummy data via MISO at the same time.
Registers of SPI Host Controller
CS register selects a SPI device to begin to communicate via SPI.
Data register is a window to write data into TX FIFO and read data from RX FIFO.
TXL (TX Level) register reports the number of elements in TX FIFO.
RXL (RX Level) register reports the number of elements in RX FIFO.
SPI Programming.
The routine SpiTransfer() transmits Request with RequestSize bytes to a SPI device and receives Response with ResponseSize bytes from the SPI device.
SpiTransfer (
IN UINT8 *Request
IN UINTN RequestSize
OUT UINT8 *Response
IN UINTN ResponseSize
)
{
Dev = GetHcDevice ();
// Select a SPI device.
Dev->Hc->CsReg = 0;
// Transmit the request to the SPI device via MOSI.
for (i = 0; i < RequestSize; i++) {
Dev->Hc->DataReg = Request [i]; // put a byte in TX FIFO.
Delay (...); // wait for transmitting the byte.
Dummy = Dev->Hc->DataReg; // clean a received dummy in RX FIFO.
}
// Clean dummy data in RX FIFO.
while (Dev->Hc->RxlReg) { // if RX FIFO has dummy data,
Dummy = Dev->Hc->DataReg; // clean the received dummy in RX FIFO.
}
// Receive a response from the SPI device via MISO.
for (i = 0; i < ResponseSize; i++) {
// put a dummy in TX FIFO to trigger CLK so that RX FIFO
// will receive data from the SPI device via MISO.
Dev->Hc->DataReg = Dummy;
Delay (...); // wait for the dummy is transmitted.
Response [i] = Dev->Hc->DataReg; // Receive data in RX FIFO.
}
// Free the SPI device.
Dev->HC->CsReg = 1;
}
-Count