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.
## **Overview**
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:
- SCLK: clock signals output from the SPI controller
- MOSI: data output from the SPI controller and input into an SPI device
- MISO: data output from an SPI device and input into the SPI controller
- CS: signals enabled by an SPI device and controlled by the SPI controller
[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.
<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**.
- SCLK: clock signal output from the SPI controller
- MOSI: data output from the SPI controller to a device
- MISO: data output from an SPI device to the 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** Connection between the SPI controller and devices
> All APIs described in this document can be called only in kernel mode.
## Usage Guidelines
### How to Use
The figure below shows the general process of using SPI.
**Figure 2** Process of using SPI APIs
![](figures/using-SPI-process.png)
### Opening an SPI Device Handle
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.
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>
</td>
</tr>
</tbody>
</table>
```
int32_t ret;
struct SpiCfg cfg = {0}; /* SPI configuration information */
cfg.mode = SPI_MODE_LOOP; /* Communication in loopback mode */
cfg.transferMode = PAL_SPI_POLLING_TRANSFER; /* Communication in polling mode */
cfg.maxSpeedHz = 115200; /* Maximum transmission frequency */
cfg.bitsPerWord = 8; /* The width of per word to be read or written is 8 bits. */
ret = SpiSetCfg(spiHandle, &cfg); /* Set SPI device configuration parameters. */
<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>
**Table 3** Description of SpiGetCfg
| **Parameter**| **Description**|
| -------- | -------- |
| handle | SPI device handle.|
| cfg | Pointer to the SPI device attributes.|
| **Return Value**| **Description**|
| 0 | The operation is successful.|
| Negative value | The operation failed.|
```
int32_t ret;
uint8_t wbuff[4] = {0x12, 0x34, 0x56, 0x78};
/* Write data of a specific length into an SPI device. */
ret = SpiWrite(spiHandle, wbuff, 4);
struct SpiCfg cfg = {0}; /* SPI configuration. */
ret = SpiGetCfg(spiHandle, &cfg); /* Obtain SPI device attributes. */
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
To read data from an SPI device only once, call the following function:
<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>
</td>
</tr>
</tbody>
</table>
### Setting SPI Device Attributes
After obtaining the SPI device handle, call **SpiSetCfg** to set SPI device attributes.
```
int32_t ret;
uint8_t rbuff[4] = {0};
/* Read data of a specific length from an SPI device. */
<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>
**Table 4** Description of SpiSetCfg
| **Parameter**| **Description**|
| -------- | -------- |
| handle | SPI device handle.|
| cfg | Pointer to the SPI device attributes.|
| **Return Value**| **Description**|
| 0 | The operation is successful.|
| Negative value | The operation failed.|
```
int32_t ret;
uint8_t wbuff[1] = {0x12};
uint8_t rbuff[1] = {0};
struct SpiMsg msg; /* Custom message to be transferred */
msg.wbuf = wbuff; /* Pointer to the data to write */
msg.rbuf = rbuff; /* Pointer to the data to read */
msg.len = 1; /* The length of the data to read or write is 1 bit. */
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);
struct SpiCfg cfg = {0}; /* SPI configuration. */
cfg.mode = SPI_MODE_LOOP; /* Communicate in loop mode. */
cfg.transferMode = PAL_SPI_POLLING_TRANSFER; /* Communicate in polling mode. */
cfg.maxSpeedHz = 115200; /* Maximum transfer frequency. */
cfg.bitsPerWord = 8; /* The width of per word to be read or written is 8 bits. */
ret = SpiSetCfg(spiHandle, &cfg); /* Set SPI device attributes. */
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"
...
...
@@ -488,61 +306,61 @@ The following example shows how to obtain an SPI device handle, set the configur
void SpiTestSample(void)
{
int32_t ret;
struct SpiCfg cfg; /* SPI device configuration information */