1e41f4b71Sopenharmony_ci# SPI
2e41f4b71Sopenharmony_ci
3e41f4b71Sopenharmony_ci
4e41f4b71Sopenharmony_ci## Overview
5e41f4b71Sopenharmony_ci
6e41f4b71Sopenharmony_ciSerial 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.
7e41f4b71Sopenharmony_ci
8e41f4b71Sopenharmony_ciSPI works in controller/device mode. Generally, there is one SPI controller that controls one or more SPI devices. They are connected via four wires:
9e41f4b71Sopenharmony_ci  - SCLK: clock signal output from the SPI controller
10e41f4b71Sopenharmony_ci  - MOSI: data output from the SPI controller to a device
11e41f4b71Sopenharmony_ci  - MISO: data output from an SPI device to the controller
12e41f4b71Sopenharmony_ci  - Chip select (CS): output from the SPI controller to indicate that data is being sent. It is controlled by the SPI controller.
13e41f4b71Sopenharmony_ci
14e41f4b71Sopenharmony_ciThe 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.
15e41f4b71Sopenharmony_ci
16e41f4b71Sopenharmony_ci  **Figure 1** Connection between the SPI controller and devices
17e41f4b71Sopenharmony_ci
18e41f4b71Sopenharmony_ci  ![image](figures/spi-controller-device-connection.png)
19e41f4b71Sopenharmony_ci
20e41f4b71Sopenharmony_ci- SPI communication is usually initiated by the controller and is performed as follows:
21e41f4b71Sopenharmony_ci  1. The SPI controller selects a device to communicate on the select line. Only one device can be selected at a time.
22e41f4b71Sopenharmony_ci  2. SCLK provides clock signals to the selected device.
23e41f4b71Sopenharmony_ci  3. The SPI controller sends data to the device via MOSI, and receives data from the devices via MISO.
24e41f4b71Sopenharmony_ci
25e41f4b71Sopenharmony_ci- SPI can work in one of the following modes according to the combination of Clock Polarity (CPOL) and Clock Phase (CPHA) of the clock signal:
26e41f4b71Sopenharmony_ci  - If both CPOL and CPHA are **0**, the clock signal level is low in the idle state and data is sampled on the first clock edge.
27e41f4b71Sopenharmony_ci  - If CPOL is **0** and CPHA is **1**, the clock signal level is low in the idle state and data is sampled on the second clock edge.
28e41f4b71Sopenharmony_ci  - If CPOL is **1** and CPHA is **0**, the clock signal level is high in the idle state and data is sampled on the first clock edge.
29e41f4b71Sopenharmony_ci  - If both CPOL and CPHA are **1**, the clock signal level is high in the idle state and data is sampled on the second clock edge.
30e41f4b71Sopenharmony_ci
31e41f4b71Sopenharmony_ci- SPI defines a set of common functions for operating an SPI device, including those for:
32e41f4b71Sopenharmony_ci  - Obtaining and releasing an SPI device handle.
33e41f4b71Sopenharmony_ci  - Reading or writing data of the specified length from or into an SPI device.
34e41f4b71Sopenharmony_ci  - Customizing data reading or writing via **SpiMsg**.
35e41f4b71Sopenharmony_ci  - Obtaining and setting SPI device attributes.
36e41f4b71Sopenharmony_ci
37e41f4b71Sopenharmony_ci> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**<br>
38e41f4b71Sopenharmony_ci> Currently, these functions are only applicable in the communication initiated by the SPI controller.
39e41f4b71Sopenharmony_ci
40e41f4b71Sopenharmony_ci
41e41f4b71Sopenharmony_ci## Available APIs
42e41f4b71Sopenharmony_ci
43e41f4b71Sopenharmony_ci  **Table 1** SPI driver APIs
44e41f4b71Sopenharmony_ci
45e41f4b71Sopenharmony_ci| API| Description|
46e41f4b71Sopenharmony_ci| -------- | -------- |
47e41f4b71Sopenharmony_ci| SpiOpen | Opens an SPI device handle.|
48e41f4b71Sopenharmony_ci| SpiClose | Closes an SPI device handle.|
49e41f4b71Sopenharmony_ci| SpiRead | Reads data of the specified length from a device.|
50e41f4b71Sopenharmony_ci| SpiWrite | Writes data of the specified length to a device.|
51e41f4b71Sopenharmony_ci| SpiTransfer | Transfers SPI data.|
52e41f4b71Sopenharmony_ci| SpiSetCfg | Sets SPI device attributes.|
53e41f4b71Sopenharmony_ci| SpiGetCfg | Obtains SPI device attributes.|
54e41f4b71Sopenharmony_ci
55e41f4b71Sopenharmony_ci> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**<br>
56e41f4b71Sopenharmony_ci> All APIs described in this document can be called only in kernel mode.
57e41f4b71Sopenharmony_ci
58e41f4b71Sopenharmony_ci
59e41f4b71Sopenharmony_ci## Usage Guidelines
60e41f4b71Sopenharmony_ci
61e41f4b71Sopenharmony_ci
62e41f4b71Sopenharmony_ci### How to Use
63e41f4b71Sopenharmony_ci
64e41f4b71Sopenharmony_ciThe figure below shows the general process of using SPI.
65e41f4b71Sopenharmony_ci
66e41f4b71Sopenharmony_ci  **Figure 2** Process of using SPI APIs
67e41f4b71Sopenharmony_ci
68e41f4b71Sopenharmony_ci  ![](figures/using-SPI-process.png)
69e41f4b71Sopenharmony_ci
70e41f4b71Sopenharmony_ci
71e41f4b71Sopenharmony_ci### Opening an SPI Device Handle
72e41f4b71Sopenharmony_ci
73e41f4b71Sopenharmony_ciBefore 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.
74e41f4b71Sopenharmony_ci
75e41f4b71Sopenharmony_ci
76e41f4b71Sopenharmony_ci```
77e41f4b71Sopenharmony_ciDevHandle SpiOpen(const struct SpiDevInfo *info); 
78e41f4b71Sopenharmony_ci```
79e41f4b71Sopenharmony_ci
80e41f4b71Sopenharmony_ci  **Table 2** Description of SpiOpen
81e41f4b71Sopenharmony_ci
82e41f4b71Sopenharmony_ci| **Parameter**| **Description**|
83e41f4b71Sopenharmony_ci| -------- | -------- |
84e41f4b71Sopenharmony_ci| info | Pointer to the SPI device descriptor.|
85e41f4b71Sopenharmony_ci| **Return Value**| **Description**|
86e41f4b71Sopenharmony_ci| NULL | The operation failed.|
87e41f4b71Sopenharmony_ci| Device handle| The operation is successful. The SPI device handle obtained is returned.|
88e41f4b71Sopenharmony_ci
89e41f4b71Sopenharmony_ciFor example, open the handle of the SPI device, whose bus number and the CS number are both **0**.
90e41f4b71Sopenharmony_ci
91e41f4b71Sopenharmony_ci
92e41f4b71Sopenharmony_ci```
93e41f4b71Sopenharmony_cistruct SpiDevInfo spiDevinfo;       /* SPI device descriptor. */
94e41f4b71Sopenharmony_ciDevHandle spiHandle = NULL;         /* SPI device handle */
95e41f4b71Sopenharmony_cispiDevinfo.busNum = 0;              /* SPI device bus number. */
96e41f4b71Sopenharmony_cispiDevinfo.csNum = 0;               /* SPI device CS number. */
97e41f4b71Sopenharmony_ci
98e41f4b71Sopenharmony_ci/* Obtain the SPI device handle. */
99e41f4b71Sopenharmony_cispiHandle = SpiOpen(&spiDevinfo);
100e41f4b71Sopenharmony_ciif (spiHandle == NULL) {
101e41f4b71Sopenharmony_ci    HDF_LOGE("SpiOpen: failed\n");
102e41f4b71Sopenharmony_ci    return;
103e41f4b71Sopenharmony_ci}
104e41f4b71Sopenharmony_ci```
105e41f4b71Sopenharmony_ci
106e41f4b71Sopenharmony_ci
107e41f4b71Sopenharmony_ci### Obtaining SPI Device Attributes
108e41f4b71Sopenharmony_ci
109e41f4b71Sopenharmony_ciAfter 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.
110e41f4b71Sopenharmony_ci
111e41f4b71Sopenharmony_ci
112e41f4b71Sopenharmony_ci```
113e41f4b71Sopenharmony_ciint32_t SpiGetCfg(DevHandle handle, struct SpiCfg *cfg);
114e41f4b71Sopenharmony_ci```
115e41f4b71Sopenharmony_ci
116e41f4b71Sopenharmony_ci  **Table 3** Description of SpiGetCfg
117e41f4b71Sopenharmony_ci
118e41f4b71Sopenharmony_ci| **Parameter**| **Description**|
119e41f4b71Sopenharmony_ci| -------- | -------- |
120e41f4b71Sopenharmony_ci| handle     | SPI device handle.|
121e41f4b71Sopenharmony_ci| cfg        | Pointer to the SPI device attributes.|
122e41f4b71Sopenharmony_ci| **Return Value**| **Description**|
123e41f4b71Sopenharmony_ci| 0          | The operation is successful.|
124e41f4b71Sopenharmony_ci| Negative value      | The operation failed.|
125e41f4b71Sopenharmony_ci
126e41f4b71Sopenharmony_ci
127e41f4b71Sopenharmony_ci```
128e41f4b71Sopenharmony_ciint32_t ret;
129e41f4b71Sopenharmony_cistruct SpiCfg cfg = {0};                /* SPI configuration. */
130e41f4b71Sopenharmony_ciret = SpiGetCfg(spiHandle, &cfg);       /* Obtain SPI device attributes. */
131e41f4b71Sopenharmony_ciif (ret != 0) {
132e41f4b71Sopenharmony_ci    HDF_LOGE("SpiGetCfg: failed, ret %d\n", ret);
133e41f4b71Sopenharmony_ci}
134e41f4b71Sopenharmony_ci```
135e41f4b71Sopenharmony_ci
136e41f4b71Sopenharmony_ci
137e41f4b71Sopenharmony_ci### Setting SPI Device Attributes
138e41f4b71Sopenharmony_ci
139e41f4b71Sopenharmony_ciAfter obtaining the SPI device handle, call **SpiSetCfg** to set SPI device attributes.
140e41f4b71Sopenharmony_ci
141e41f4b71Sopenharmony_ci
142e41f4b71Sopenharmony_ci```
143e41f4b71Sopenharmony_ciint32_t SpiSetCfg(DevHandle handle, struct SpiCfg *cfg);
144e41f4b71Sopenharmony_ci```
145e41f4b71Sopenharmony_ci
146e41f4b71Sopenharmony_ci  **Table 4** Description of SpiSetCfg
147e41f4b71Sopenharmony_ci
148e41f4b71Sopenharmony_ci| **Parameter**| **Description**|
149e41f4b71Sopenharmony_ci| -------- | -------- |
150e41f4b71Sopenharmony_ci| handle     | SPI device handle.|
151e41f4b71Sopenharmony_ci| cfg        | Pointer to the SPI device attributes.|
152e41f4b71Sopenharmony_ci| **Return Value**| **Description**|
153e41f4b71Sopenharmony_ci| 0          | The operation is successful.|
154e41f4b71Sopenharmony_ci| Negative value      | The operation failed.|
155e41f4b71Sopenharmony_ci
156e41f4b71Sopenharmony_ci
157e41f4b71Sopenharmony_ci```
158e41f4b71Sopenharmony_ciint32_t ret;
159e41f4b71Sopenharmony_cistruct SpiCfg cfg = {0};                     /* SPI configuration. */
160e41f4b71Sopenharmony_cicfg.mode = SPI_MODE_LOOP;                    /* Communicate in loop mode. */
161e41f4b71Sopenharmony_cicfg.transferMode = PAL_SPI_POLLING_TRANSFER; /* Communicate in polling mode. */
162e41f4b71Sopenharmony_cicfg.maxSpeedHz = 115200;                     /* Maximum transfer frequency. */
163e41f4b71Sopenharmony_cicfg.bitsPerWord = 8;                         /* The width of per word to be read or written is 8 bits. */
164e41f4b71Sopenharmony_ciret = SpiSetCfg(spiHandle, &cfg);            /* Set SPI device attributes. */
165e41f4b71Sopenharmony_ciif (ret != 0) {
166e41f4b71Sopenharmony_ci    HDF_LOGE("SpiSetCfg: failed, ret %d\n", ret);
167e41f4b71Sopenharmony_ci}
168e41f4b71Sopenharmony_ci```
169e41f4b71Sopenharmony_ci
170e41f4b71Sopenharmony_ci
171e41f4b71Sopenharmony_ci### Performing SPI Communication
172e41f4b71Sopenharmony_ci
173e41f4b71Sopenharmony_ci- Write data to an SPI device
174e41f4b71Sopenharmony_ci
175e41f4b71Sopenharmony_ci  Call **SpiWrite()** to write data to an SPI device only once.
176e41f4b71Sopenharmony_ci
177e41f4b71Sopenharmony_ci
178e41f4b71Sopenharmony_ci  ```
179e41f4b71Sopenharmony_ci  int32_t SpiWrite(DevHandle handle, uint8_t *buf, uint32_t len);
180e41f4b71Sopenharmony_ci  ```
181e41f4b71Sopenharmony_ci
182e41f4b71Sopenharmony_ci  **Table 5** Description of SpiWrite
183e41f4b71Sopenharmony_ci
184e41f4b71Sopenharmony_ci| **Parameter**| **Description**|
185e41f4b71Sopenharmony_ci| -------- | -------- |
186e41f4b71Sopenharmony_ci| handle     | SPI device handle.|
187e41f4b71Sopenharmony_ci| buf        | Pointer to the data to write.|
188e41f4b71Sopenharmony_ci| len        | Length of the data to write.|
189e41f4b71Sopenharmony_ci| **Return Value**| **Description**|
190e41f4b71Sopenharmony_ci| 0          | The operation is successful.|
191e41f4b71Sopenharmony_ci| Negative value      | The operation failed.|
192e41f4b71Sopenharmony_ci
193e41f4b71Sopenharmony_ci
194e41f4b71Sopenharmony_ci  ```
195e41f4b71Sopenharmony_ci  int32_t ret;
196e41f4b71Sopenharmony_ci  uint8_t wbuff[4] = {0x12, 0x34, 0x56, 0x78};
197e41f4b71Sopenharmony_ci  /* Write data of the specified length to an SPI device. */
198e41f4b71Sopenharmony_ci  ret = SpiWrite(spiHandle, wbuff, 4);
199e41f4b71Sopenharmony_ci  if (ret != 0) {
200e41f4b71Sopenharmony_ci      HDF_LOGE("SpiWrite: failed, ret %d\n", ret);
201e41f4b71Sopenharmony_ci  }
202e41f4b71Sopenharmony_ci  ```
203e41f4b71Sopenharmony_ci
204e41f4b71Sopenharmony_ci- Read data from an SPI device
205e41f4b71Sopenharmony_ci
206e41f4b71Sopenharmony_ci  Call **SpiRead()** to read data from an SPI device only once.
207e41f4b71Sopenharmony_ci
208e41f4b71Sopenharmony_ci
209e41f4b71Sopenharmony_ci  ```
210e41f4b71Sopenharmony_ci  int32_t SpiRead(DevHandle handle, uint8_t *buf, uint32_t len); 
211e41f4b71Sopenharmony_ci  ```
212e41f4b71Sopenharmony_ci
213e41f4b71Sopenharmony_ci  **Table 6** Description of SpiRead
214e41f4b71Sopenharmony_ci
215e41f4b71Sopenharmony_ci| **Parameter**| **Description**|
216e41f4b71Sopenharmony_ci| -------- | -------- |
217e41f4b71Sopenharmony_ci| handle | SPI device handle.|
218e41f4b71Sopenharmony_ci| buf | Pointer to the data to read.|
219e41f4b71Sopenharmony_ci| len | Length of the data to read.|
220e41f4b71Sopenharmony_ci| **Return Value**| **Description**|
221e41f4b71Sopenharmony_ci| 0 | The operation is successful.|
222e41f4b71Sopenharmony_ci| Negative value| The operation failed.|
223e41f4b71Sopenharmony_ci
224e41f4b71Sopenharmony_ci
225e41f4b71Sopenharmony_ci  ```
226e41f4b71Sopenharmony_ci  int32_t ret;
227e41f4b71Sopenharmony_ci  uint8_t rbuff[4] = {0};
228e41f4b71Sopenharmony_ci  /* Read data of the specified length from an SPI device. */
229e41f4b71Sopenharmony_ci  ret = SpiRead(spiHandle, rbuff, 4);
230e41f4b71Sopenharmony_ci  if (ret != 0) {
231e41f4b71Sopenharmony_ci      HDF_LOGE("SpiRead: failed, ret %d\n", ret);
232e41f4b71Sopenharmony_ci  }
233e41f4b71Sopenharmony_ci  ```
234e41f4b71Sopenharmony_ci
235e41f4b71Sopenharmony_ci- Perform a custom transfer
236e41f4b71Sopenharmony_ci
237e41f4b71Sopenharmony_ci  Call **SpiTransfer()** to perform a custom transfer.
238e41f4b71Sopenharmony_ci
239e41f4b71Sopenharmony_ci
240e41f4b71Sopenharmony_ci  ```
241e41f4b71Sopenharmony_ci  int32_t SpiTransfer(DevHandle handle, struct SpiMsg *msgs, uint32_t count);
242e41f4b71Sopenharmony_ci  ```
243e41f4b71Sopenharmony_ci
244e41f4b71Sopenharmony_ci  **Table 7** Description of SpiTransfer
245e41f4b71Sopenharmony_ci
246e41f4b71Sopenharmony_ci| **Parameter**| **Description**|
247e41f4b71Sopenharmony_ci| -------- | -------- |
248e41f4b71Sopenharmony_ci| handle | SPI device handle.|
249e41f4b71Sopenharmony_ci| msgs | Pointer to the message array to be transferred.|
250e41f4b71Sopenharmony_ci| count | Number of messages in the message array.|
251e41f4b71Sopenharmony_ci| **Return Value**| **Description**|
252e41f4b71Sopenharmony_ci| 0 | The operation is successful.|
253e41f4b71Sopenharmony_ci| Negative value| The operation failed.|
254e41f4b71Sopenharmony_ci
255e41f4b71Sopenharmony_ci
256e41f4b71Sopenharmony_ci  ```
257e41f4b71Sopenharmony_ci  int32_t ret;
258e41f4b71Sopenharmony_ci  uint8_t wbuff[1] = {0x12};
259e41f4b71Sopenharmony_ci  uint8_t rbuff[1] = {0};
260e41f4b71Sopenharmony_ci  struct SpiMsg msg;        /* Custom message to be transferred. */
261e41f4b71Sopenharmony_ci  msg.wbuf = wbuff;         /* Data to write. */
262e41f4b71Sopenharmony_ci  msg.rbuf = rbuff;         /* Data to read. */
263e41f4b71Sopenharmony_ci  msg.len = 1;              /* The length of the data to read or write is 1 bit. */
264e41f4b71Sopenharmony_ci  msg.csChange = 1;         /* Close the CS before the next transfer. */
265e41f4b71Sopenharmony_ci  msg.delayUs = 0;          /* No delay before the next transfer. */
266e41f4b71Sopenharmony_ci  msg.speed = 115200;       /* Transfer speed. */
267e41f4b71Sopenharmony_ci  /* Perform a custom transfer. The number of messages to be transferred is 1. */
268e41f4b71Sopenharmony_ci  ret = SpiTransfer(spiHandle, &msg, 1);
269e41f4b71Sopenharmony_ci  if (ret != 0) {
270e41f4b71Sopenharmony_ci      HDF_LOGE("SpiTransfer: failed, ret %d\n", ret);
271e41f4b71Sopenharmony_ci  }
272e41f4b71Sopenharmony_ci  ```
273e41f4b71Sopenharmony_ci
274e41f4b71Sopenharmony_ci
275e41f4b71Sopenharmony_ci### Closing an SPI Device Handle
276e41f4b71Sopenharmony_ci
277e41f4b71Sopenharmony_ciAfter the SPI communication, call **SpiClose()** to close the SPI device handle.
278e41f4b71Sopenharmony_ci
279e41f4b71Sopenharmony_ci
280e41f4b71Sopenharmony_ci```
281e41f4b71Sopenharmony_civoid SpiClose(DevHandle handle);
282e41f4b71Sopenharmony_ci```
283e41f4b71Sopenharmony_ci
284e41f4b71Sopenharmony_ciThis function releases the resources requested by **MipiDsiOpen**.
285e41f4b71Sopenharmony_ci
286e41f4b71Sopenharmony_ci  **Table 8** Description of SpiClose
287e41f4b71Sopenharmony_ci
288e41f4b71Sopenharmony_ci| **Parameter**| **Description**|
289e41f4b71Sopenharmony_ci| -------- | -------- |
290e41f4b71Sopenharmony_ci| handle | SPI device handle.|
291e41f4b71Sopenharmony_ci
292e41f4b71Sopenharmony_ci
293e41f4b71Sopenharmony_ci```
294e41f4b71Sopenharmony_ciSpiClose(spiHandle); /* Close the SPI device handle. */
295e41f4b71Sopenharmony_ci```
296e41f4b71Sopenharmony_ci
297e41f4b71Sopenharmony_ci
298e41f4b71Sopenharmony_ci## Example
299e41f4b71Sopenharmony_ci
300e41f4b71Sopenharmony_ciThe 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.
301e41f4b71Sopenharmony_ci
302e41f4b71Sopenharmony_ci```
303e41f4b71Sopenharmony_ci#include "hdf_log.h"
304e41f4b71Sopenharmony_ci#include "spi_if.h"
305e41f4b71Sopenharmony_ci
306e41f4b71Sopenharmony_civoid SpiTestSample(void)
307e41f4b71Sopenharmony_ci{
308e41f4b71Sopenharmony_ci    int32_t ret;
309e41f4b71Sopenharmony_ci    struct SpiCfg cfg;                  /* SPI device configuration. */
310e41f4b71Sopenharmony_ci    struct SpiDevInfo spiDevinfo;       /* SPI device descriptor. */
311e41f4b71Sopenharmony_ci    DevHandle spiHandle = NULL; /* SPI device handle. */
312e41f4b71Sopenharmony_ci    struct SpiMsg msg;                  /* Custom message to be transferred. */
313e41f4b71Sopenharmony_ci    uint8_t rbuff[4] = { 0 };
314e41f4b71Sopenharmony_ci    uint8_t wbuff[4] = { 0x12, 0x34, 0x56, 0x78 };
315e41f4b71Sopenharmony_ci    uint8_t wbuff2[4] = { 0xa1, 0xb2, 0xc3, 0xd4 };
316e41f4b71Sopenharmony_ci
317e41f4b71Sopenharmony_ci    spiDevinfo.busNum = 0;              /* SPI device bus number. */
318e41f4b71Sopenharmony_ci    spiDevinfo.csNum = 0;               /* SPI device CS number. */
319e41f4b71Sopenharmony_ci    spiHandle = SpiOpen(&spiDevinfo);   /* Open the SPI device handle based on spiDevinfo. */
320e41f4b71Sopenharmony_ci    if (spiHandle == NULL) {
321e41f4b71Sopenharmony_ci        HDF_LOGE("SpiOpen: failed\n");
322e41f4b71Sopenharmony_ci        return;
323e41f4b71Sopenharmony_ci    }
324e41f4b71Sopenharmony_ci    /* Obtain SPI attributes. */
325e41f4b71Sopenharmony_ci    ret = SpiGetCfg(spiHandle, &cfg);
326e41f4b71Sopenharmony_ci    if (ret != 0) {
327e41f4b71Sopenharmony_ci        HDF_LOGE("SpiGetCfg: failed, ret %d\n", ret);
328e41f4b71Sopenharmony_ci        goto err;
329e41f4b71Sopenharmony_ci    }
330e41f4b71Sopenharmony_ci    cfg.maxSpeedHz = 115200;                /* Set the maximum clock frequency to 115200. */
331e41f4b71Sopenharmony_ci    cfg.bitsPerWord = 8;                    /* Set the word width to 8 bits. */
332e41f4b71Sopenharmony_ci    /* Set SPI attributes. */
333e41f4b71Sopenharmony_ci    ret = SpiSetCfg(spiHandle, &cfg);
334e41f4b71Sopenharmony_ci    if (ret != 0) {
335e41f4b71Sopenharmony_ci        HDF_LOGE("SpiSetCfg: failed, ret %d\n", ret);
336e41f4b71Sopenharmony_ci        goto err;
337e41f4b71Sopenharmony_ci    }
338e41f4b71Sopenharmony_ci    /* Write data of the specified length to an SPI device. */
339e41f4b71Sopenharmony_ci    ret = SpiWrite(spiHandle, wbuff, 4);
340e41f4b71Sopenharmony_ci    if (ret != 0) {
341e41f4b71Sopenharmony_ci        HDF_LOGE("SpiWrite: failed, ret %d\n", ret);
342e41f4b71Sopenharmony_ci        goto err;
343e41f4b71Sopenharmony_ci    }
344e41f4b71Sopenharmony_ci    /* Read data of the specified length from an SPI device. */
345e41f4b71Sopenharmony_ci    ret = SpiRead(spiHandle, rbuff, 4);
346e41f4b71Sopenharmony_ci    if (ret != 0) {
347e41f4b71Sopenharmony_ci        HDF_LOGE("SpiRead: failed, ret %d\n", ret);
348e41f4b71Sopenharmony_ci        goto err;
349e41f4b71Sopenharmony_ci    }
350e41f4b71Sopenharmony_ci    msg.wbuf = wbuff2;  /* Data to write. */
351e41f4b71Sopenharmony_ci    msg.rbuf = rbuff;   /* Data to read. */
352e41f4b71Sopenharmony_ci    msg.len = 4;        /* Set the length of the data to read or write to 4 bits. */
353e41f4b71Sopenharmony_ci    msg.csChange = 1;   /* Close the CS before the next transfer. */
354e41f4b71Sopenharmony_ci    msg.delayUs = 0;    /* No delay before the next transfer. */
355e41f4b71Sopenharmony_ci    msg.speed = 115200; /* Transfer speed. */
356e41f4b71Sopenharmony_ci    /* Perform a custom transfer. The number of messages to be transferred is 1. */
357e41f4b71Sopenharmony_ci    ret = SpiTransfer(spiHandle, &msg, 1);
358e41f4b71Sopenharmony_ci    if (ret != 0) {
359e41f4b71Sopenharmony_ci        HDF_LOGE("SpiTransfer: failed, ret %d\n", ret);
360e41f4b71Sopenharmony_ci        goto err;
361e41f4b71Sopenharmony_ci    }
362e41f4b71Sopenharmony_cierr:
363e41f4b71Sopenharmony_ci    /* Close the SPI device handle. */
364e41f4b71Sopenharmony_ci    SpiClose(spiHandle);
365e41f4b71Sopenharmony_ci}
366e41f4b71Sopenharmony_ci```
367