HW & SW design of the AXI Quad SPI IP core
1 Basics
SPI has three-wire mode and four-wire mode. The three-wire mode consists of three wires - SS
(Slave Select), SCK
(SPI Clock), and MOSI
(Master-In-Slave-Out). The four wire mode has an extra line called MISO
(Master-In-Slave-Out).
Signals | Full Name |
---|---|
SS | Slave Select |
SCK | SPI Clock |
MOSI | Master-Out-Slave-In |
MISO | Master-In-Slave-Out |
SPI clock has four modes: CPOL=0/1 and CPHA=0/1. CPOL stands for clock polarity – clock low or high when in idle. CPHA stands for clock phase – data valid at 0 degree or 180 degrees.
2 AXI Quad SPI IP Core
When we run out of Zynq PS SPI controllers for some reason, we can turn to PL SPI IP cores, which is called AXI Quad SPI.
In the picture, io1_i
connects to MISO; ext_spi_clk
and s_axi_clk
can be connected to a same system clock. ip2intc_irpt
can be connected to the Zynq interrupt pl_ps_irq
.
You can double-click on the IP core to configure clock divider, number of slave selects, and more.
3 Bare-Metal Programming
The programming sequence is as follows:
- First, initialize the SPI controller. Set the value of all registers to their default values.
- Next, depending on your needs, configure the SPI controller. For example, the clock mode (CPHA and CPOL) and slave select mode (auto or manual).
- Then, depending on the number of bytes need to be written and read, write to the DTR (Data Transmit Register) the corresponding number of bytes. Each written byte will be shifted into the TX FIFO.
- Note: If the number of written bytes is
n_tx
and the number of read bytes isn_rx
, then we should not only writen_tx
bytes to the DTR, but also write anothern_rx
“dummy” bytes. This is because SPI, in nature, is a full-duplex protocol – in order to receiven_rx
bytes, you also need to sendn_rx
bytes.
- Note: If the number of written bytes is
- Finally, read the bytes out of the DRR (Data Receive Register). When the DRR is read, the read byte will be dequed.
- Note: depending on the scene, when receiving from the slave, the programmer may need to discard the first
n_tx
bytes. This is because when the master is sending data/instructions, the slave may not yet respond. Rather, the slave will not respond until the master has sent all of the bytes (instruction & data). But due to the full-duplex nature of the SPI protocol, the firstn_tx
dummy bytes will also be pushed into the RX FIFO. Therefore, one may need to discard those bytes.
- Note: depending on the scene, when receiving from the slave, the programmer may need to discard the first
- If we use the manual slave select mode, we should assert the SS signal before the transfer and de-assert the SS signal after the transfer.
The following code sends two bytes [0x00 0x37]
to the slave and reads one byte from the slave.
|
|
4 Linux Programming
In order to use the AXI Quad SPI IP core in Linux, we should add a spidev
node to the device tree, so that we could achieve SPI communication by reading from or writing to the /dev/spidevx.y
device.
In
/dev/spidevx.y
,x
stands for the x-th SPI controller, andy
stands for the y-th chip.
The device tree is usually initialized during boot-up and is read-only. However, after the 4.14 version of the Linux kernel, we can use the “device tree overlay” (briefed as DTO from now on) to dynamically add incremental device trees. Below is a code snippet of DTO.
|
|
Some points to be noted:
- We should add one more line
/plugin/;
after/dts-v1/;
to show that this is an DTO file rather than an ordinary device tree file.target
stands for which node is to be modified. Here it is<&amba>
, and it will be extended to the phandle of the node which has the symbolamba
. For example, if the phandle ofamba
is70
, then<&amba>
virtually stands for<70>
. A phandle uniquely denotes a node and is usually allocated by the device tree compiler.- In most cases, we should add the
-@
compiler option, which enables support for symbol. Otherwise we can only reference the nodes by their phandle, which requires de-compiling the device tree binaries.