Serial Peripheral Interface \(SPI\) is a serial bus specification used for high-speed, full-duplex, and synchronous communication.
## **Overview**
SPI is developed by Motorola. It is commonly used for communication with flash memory, real-time clocks, sensors, and analog-to-digital \(A/D\) converters.
Serial Peripheral Interface (SPI) is a serial bus specification used for high-speed, full-duplex, and synchronous communication. SPI is developed by Motorola. It is commonly used for communication with flash memory, real-time clocks, sensors, and analog-to-digital (A/D) converters.
SPI works in controller/device mode. Generally, there is one SPI controller that controls one or more SPI devices. They are connected via four wires:
SPI works in controller/device mode. Generally, there is one SPI controller that controls one or more SPI devices. They are connected via four wires:
- SCLK: clock signals output from the SPI controller
- SCLK: clock signal output from the SPI controller
- MOSI: data output from the SPI controller and input into an SPI device
- MOSI: data output from the SPI controller to a device
- MISO: data output from an SPI device and input into the SPI controller
- MISO: data output from an SPI device to the controller
- CS: signals enabled by an SPI device and controlled by the SPI controller
- Chip select (CS): output from the SPI controller to indicate that data is being sent. It is controlled by the SPI controller.
The figure below shows the connection between one controller and two devices (device A and device B). Device A and device B share three pins (SCLK, MISO, and MOSI) of the controller. CS 0 of device A and CS 1 of device B are connected to CS 0 and CS 1 of the controller, respectively.
[Figure 1](#fig89085710359) shows the connection between one SPI controller and two SPI devices \(device A and device B\). In this figure, device A and device B share three pins \(SCLK, MISO, and MOSI\) of the controller. CS0 of device A and CS1 of device B are connected to CS0 and CS1 of the controller, respectively.
**Figure 1** Connection between the SPI controller and devices
<tdclass="cellrowborder"valign="top"width="55.77442255774422%"headers="mcps1.2.4.1.3 "><pid="p8738101941716"><aname="p8738101941716"></a><aname="p8738101941716"></a>Reads data of a specified length from an SPI device.</p>
<tdclass="cellrowborder"valign="top"headers="mcps1.2.4.1.2 "><pid="p573815197171"><aname="p573815197171"></a><aname="p573815197171"></a>Writes data of a specified length into an SPI device.</p>
<tdclass="cellrowborder"valign="top"width="55.77442255774422%"headers="mcps1.2.4.1.3 "><pid="p073910197173"><aname="p073910197173"></a><aname="p073910197173"></a>Sets configuration parameters for an SPI device.</p>
<tdclass="cellrowborder"valign="top"headers="mcps1.2.4.1.2 "><pid="p11333649171117"><aname="p11333649171117"></a><aname="p11333649171117"></a>Obtains configuration parameters of an SPI device.</p>
### Obtaining an SPI Device Handle<a name="section1927265711481"></a>
Before performing SPI communication, obtain an SPI device handle by calling **SpiOpen**. This function returns an SPI device handle with a specified bus number and CS number.
<tdclass="cellrowborder"valign="top"width="50%"><pid="p1560441923818"><aname="p1560441923818"></a><aname="p1560441923818"></a>Pointer to the SPI device descriptor.</p>
<tdclass="cellrowborder"valign="top"width="50%"><pid="p760471912388"><aname="p760471912388"></a><aname="p760471912388"></a>Failed to obtain an SPI device handle.</p>
<tdclass="cellrowborder"valign="top"width="50%"><pid="p3604181933818"><aname="p3604181933818"></a><aname="p3604181933818"></a>Returns the pointer to the SPI device handle.</p>
</td>
</tr>
</tbody>
</table>
The following example shows how to obtain an SPI device handle based on the assumption that both the bus number and CS number of the SPI device are **0**.
Before performing SPI communication, call **SpiOpen** to open the SPI device handle. This function returns the device handle of the SPI based on the specified bus number and CS number.
<tdclass="cellrowborder"valign="top"width="50%"><pid="p72101252101312"><aname="p72101252101312"></a><aname="p72101252101312"></a>Failed to obtain SPI device configuration parameters.</p>
</td>
</tr>
</tbody>
</table>
```
### Obtaining SPI Device Attributes
int32_t ret;
struct SpiCfg cfg = {0}; /* SPI configuration information */
After obtaining the SPI device handle, you need to configure the device attributes. Before configuring the device attributes, you can call **SpiGetCfg** to obtain the device attributes.
<tdclass="cellrowborder"valign="top"width="50%"><pid="p20191192925212"><aname="p20191192925212"></a><aname="p20191192925212"></a>Failed to set SPI device configuration parameters.</p>
<tdclass="cellrowborder"valign="top"width="50%"><pid="p16905313854"><aname="p16905313854"></a><aname="p16905313854"></a>Length of the data to write.</p>
<tdclass="cellrowborder"valign="top"width="50%"><pid="p1231981611712"><aname="p1231981611712"></a><aname="p1231981611712"></a>Succeeded in writing data into an SPI device.</p>
<tdclass="cellrowborder"valign="top"width="50%"><pid="p93191161174"><aname="p93191161174"></a><aname="p93191161174"></a>Failed to write data into an SPI device.</p>
</td>
</tr>
</tbody>
</table>
```
```
int32_t ret;
int32_t ret;
uint8_t wbuff[4] = {0x12, 0x34, 0x56, 0x78};
struct SpiCfg cfg = {0}; /* SPI configuration. */
/* Write data of a specific length into an SPI device. */
ret = SpiGetCfg(spiHandle, &cfg); /* Obtain SPI device attributes. */
ret = SpiWrite(spiHandle, wbuff, 4);
if (ret != 0) {
if (ret != 0) {
HDF_LOGE("SpiWrite: failed, ret %d\n", ret);
HDF_LOGE("SpiGetCfg: failed, ret %d\n", ret);
}
}
```
```
- Reading data of a specific length from an SPI device
### Setting SPI Device Attributes
To read data from an SPI device only once, call the following function:
After obtaining the SPI device handle, call **SpiSetCfg** to set SPI device attributes.
<tdclass="cellrowborder"valign="top"width="50%"><pid="p98131811126"><aname="p98131811126"></a><aname="p98131811126"></a>Pointer to the data to read.</p>
<tdclass="cellrowborder"valign="top"width="50%"><pid="p169718191220"><aname="p169718191220"></a><aname="p169718191220"></a>Length of the data to read.</p>
<tdclass="cellrowborder"valign="top"width="50%"><pid="p88118101211"><aname="p88118101211"></a><aname="p88118101211"></a>Succeeded in reading data from an SPI device.</p>
<tdclass="cellrowborder"valign="top"width="50%"><pid="p986183127"><aname="p986183127"></a><aname="p986183127"></a>Failed to read data from an SPI device.</p>
<tdclass="cellrowborder"valign="top"width="50%"><pid="p202951238218"><aname="p202951238218"></a><aname="p202951238218"></a>Pointer to the message array to be transferred.</p>
<tdclass="cellrowborder"valign="top"width="50%"><pid="p259124622119"><aname="p259124622119"></a><aname="p259124622119"></a>Number of messages in the message array.</p>
<tdclass="cellrowborder"valign="top"width="50%"><pid="p829512237217"><aname="p829512237217"></a><aname="p829512237217"></a>Succeeded in launching the custom transfer.</p>
<tdclass="cellrowborder"valign="top"width="50%"><pid="p1295192312112"><aname="p1295192312112"></a><aname="p1295192312112"></a>Failed to launch the custom transfer.</p>
</td>
</tr>
</tbody>
</table>
```
```
int32_t ret;
int32_t ret;
uint8_t wbuff[1] = {0x12};
struct SpiCfg cfg = {0}; /* SPI configuration. */
uint8_t rbuff[1] = {0};
cfg.mode = SPI_MODE_LOOP; /* Communicate in loop mode. */
struct SpiMsg msg; /* Custom message to be transferred */
cfg.transferMode = PAL_SPI_POLLING_TRANSFER; /* Communicate in polling mode. */
msg.wbuf = wbuff; /* Pointer to the data to write */
cfg.maxSpeedHz = 115200; /* Maximum transfer frequency. */
msg.rbuf = rbuff; /* Pointer to the data to read */
cfg.bitsPerWord = 8; /* The width of per word to be read or written is 8 bits. */
msg.len = 1; /* The length of the data to read or write is 1 bit. */
ret = SpiSetCfg(spiHandle, &cfg); /* Set SPI device attributes. */
msg.csChange = 1; /* Disable the CS before the next transfer. */
msg.delayUs = 0; /* No delay before the next transfer */
msg.speed = 115200; /* Speed of this transfer */
/* Launch a custom transfer. The number of messages to be transferred is 1. */
ret = SpiTransfer(spiHandle, &msg, 1);
if (ret != 0) {
if (ret != 0) {
HDF_LOGE("SpiTransfer: failed, ret %d\n", ret);
HDF_LOGE("SpiSetCfg: failed, ret %d\n", ret);
}
}
```
```
### Destroying the SPI Device Handle<a name="section19661632135117"></a>
After the SPI communication, destroy the SPI device handle by calling the following function:
### Performing SPI Communication
- Write data to an SPI device
Call **SpiWrite()** to write data to an SPI device only once.
This function releases the resources requested by **MipiDsiOpen**.
**Table 8** Description of SpiClose
The following example shows how to obtain an SPI device handle, set the configuration parameters, and then read or write data from or into the SPI device, and finally destroy the SPI device handle.
| **Parameter**| **Description**|
| -------- | -------- |
| handle | SPI device handle.|
```
SpiClose(spiHandle); /* Close the SPI device handle. */
```
## Example
The following example shows how to obtain an SPI device handle, set device attributes, and then read or write data from or into the SPI device, and finally close the SPI device handle.
```
```
#include "hdf_log.h"
#include "hdf_log.h"
...
@@ -488,61 +306,61 @@ The following example shows how to obtain an SPI device handle, set the configur
...
@@ -488,61 +306,61 @@ The following example shows how to obtain an SPI device handle, set the configur
void SpiTestSample(void)
void SpiTestSample(void)
{
{
int32_t ret;
int32_t ret;
struct SpiCfg cfg; /* SPI device configuration information */