# SPI HAL interface documentation

## Hardware introduction

K230 integrates 3 SPI controllers (SPI0~SPI2) internally and supports host mode. Supports standard SPI modes (MODE0~MODE3), and the data bit width is configurable from 4 to 32 bits. Supports single-wire, dual-wire, four-wire and eight-wire (SPI0 only) transmission modes. Supports QSPI extended functions, including stage configurations such as instructions, addresses, dummy cycles, etc.

---

## Data structure description

### SPI mode definition

- `SPI_HAL_MODE_0`: CPOL = 0, CPHA = 0
- `SPI_HAL_MODE_1`: CPOL = 0, CPHA = 1
- `SPI_HAL_MODE_2`: CPOL = 1, CPHA = 0
- `SPI_HAL_MODE_3`: CPOL = 1, CPHA = 1

### Data line configuration

- `SPI_HAL_DATA_LINE_1`: Single Wire SPI
- `SPI_HAL_DATA_LINE_2`: Dual-wire SPI
- `SPI_HAL_DATA_LINE_4`: Four-wire QSPI
- `SPI_HAL_DATA_LINE_8`: Eight-line SPI (only supported by SPI0)

### `drv_spi_inst_t`

**Description**: SPI instance handle type.

### `rt_spi_message`

**Description**: SPI message structure.

- `send_buf`: Send data buffer
- `recv_buf`: receive data buffer
- `length`: data length
- `next`: next message (linked list)
- `cs_take`: Whether to lower the chip select
- `cs_release`: Whether to release the chip select

### `rt_qspi_message`

**Description**: QSPI extended message structure, inherited from `rt_spi_message`.

- `instruction`: command phase configuration
- `address`: Address phase configuration
- `alternate_bytes`: Alternate byte phase configuration
- `dummy_cycles`: dummy cycle number
- `qspi_data_lines`: Number of data lines used in the data stage

---

## Function interface description

### `int drv_spi_inst_create(int spi_id, bool active_low, int mode, uint32_t baudrate, uint8_t data_bits, int cs_pin, uint8_t data_line, drv_spi_inst_t *inst);`

**Function**: Create SPI instance.

**parameter**:

- `spi_id`: SPI controller number, range `[0, 2]`
- `active_low`: Chip select signal polarity, `true` is active at low level, `false` is active at high level
- `mode`: SPI mode (`SPI_HAL_MODE_0` ~ `SPI_HAL_MODE_3`)
- `baudrate`: clock frequency (Hz)
- `data_bits`: Data bit width, range `[4, 32]`
- `cs_pin`: chip select pin number, range `[0, 63]`, `-1` means chip select is controlled externally
- `data_line`: Number of data lines (1/2/4/8)
- `inst`: used to store the created SPI instance pointer

**Return Value**:

- `0`: Success
- `Negative value`: failed

---

### `void drv_spi_inst_destroy(drv_spi_inst_t *inst);`

**Function**: Destroy SPI instance and release resources.

**parameter**:

- `inst`: Pointer to SPI instance pointer

---

### `int drv_spi_transfer(drv_spi_inst_t inst, const void *tx_data, void *rx_data, size_t len, bool cs_change);`

**FEATURE**: Full-duplex SPI transfer.

**parameter**:

- `inst`: SPI instance
- `tx_data`: Send data buffer, `NULL` means read-only
- `rx_data`: receive data buffer, `NULL` means write only
- `len`: Data length (bytes)
- `cs_change`: `true` means releasing the chip select after transmission, `false` means keeping the chip select

**Return Value**:

- `Positive value`: Number of bytes actually transferred
- `Negative value`: failed

---

### `int drv_spi_read(drv_spi_inst_t inst, void *rx_data, size_t len, bool cs_change);`

**Function**: SPI read operation.

**parameter**:

- `inst`: SPI instance
- `rx_data`: receive data buffer
- `len`: read length (bytes)
- `cs_change`: `true` means releasing the chip select after transmission, `false` means keeping the chip select

**Return Value**:

- `Positive value`: Number of bytes actually read
- `Negative value`: failed

---

### `int drv_spi_write(drv_spi_inst_t inst, const void *tx_data, size_t len, bool cs_change);`

**Function**: SPI write operation.

**parameter**:

- `inst`: SPI instance
- `tx_data`: Send data buffer
- `len`: write length (bytes)
- `cs_change`: `true` means releasing the chip select after transmission, `false` means keeping the chip select

**Return Value**:

- `Positive value`: Number of bytes actually written
- `Negative value`: failed

---

### `int drv_spi_transfer_message(drv_spi_inst_t inst, struct rt_qspi_message *msg);`

**Function**: Advanced QSPI transmission, supports configuration of instructions, addresses, dummy cycles, etc.

**parameter**:

- `inst`: SPI instance
- `msg`: QSPI message structure

**Return Value**:

- `Positive value`: Number of bytes actually transferred
- `Negative value`: failed

---

## Usage example

Please refer to `src/rtsmart/libs/testcases/rtsmart_hal/test_spi_st7789.c` and `src/rtsmart/libs/testcases/rtsmart_hal/test_spi_wq128.c`

**Note**:

1. Before using SPI, you need to configure the corresponding pin functions (CLK, MOSI, MISO, etc.) through FPIOA.
1. 8-wire mode is only supported by SPI0.
1. When the chip select pin is set to -1, external control of the chip select signal is required, and the `cs_change` parameter will have no effect.
1. drv_spi_transfer_message supports hardware chip selection, and other hal interfaces only support software chip selection.
