2023-12-28 01:19:05 +08:00
|
|
|
# SPI Devices
|
|
|
|
|
|
|
|
|
|
[中文](spi.md)
|
|
|
|
|
|
|
|
|
|
<!-- TOC -->
|
|
|
|
|
* [SPI Devices](#spi-devices)
|
|
|
|
|
* [Register SPI Device](#register-spi-device)
|
|
|
|
|
* [Open SPI Device](#open-spi-device)
|
|
|
|
|
* [Close SPI Device](#close-spi-device)
|
|
|
|
|
* [Control SPI Device](#control-spi-device)
|
|
|
|
|
* [Set/Get SPI Device Configuration](#setget-spi-device-configuration)
|
|
|
|
|
* [Set/Get Register Value](#setget-register-value)
|
|
|
|
|
* [Set/Get Read Buffer Size](#setget-read-buffer-size)
|
|
|
|
|
* [Clear Read Buffer](#clear-read-buffer)
|
|
|
|
|
* [Get Read Buffer Data Size](#get-read-buffer-data-size)
|
|
|
|
|
* [Set/Get Read Callback Function](#setget-read-callback-function)
|
|
|
|
|
* [Full-Duplex Transmission](#full-duplex-transmission)
|
|
|
|
|
* [Read SPI Device Data](#read-spi-device-data)
|
|
|
|
|
* [Write SPI Device Data](#write-spi-device-data)
|
|
|
|
|
* [Usage Example:](#usage-example)
|
|
|
|
|
<!-- TOC -->
|
|
|
|
|
|
|
|
|
|
Note: SPI-CS control requires enabling the PIN device.
|
|
|
|
|
|
|
|
|
|
## Register SPI Device
|
|
|
|
|
|
|
|
|
|
```c
|
2024-01-31 22:45:56 +08:00
|
|
|
int mr_spi_dev_register(struct mr_spi_dev *spi_dev, const char *path, int cs_pin, int cs_active);
|
2023-12-28 01:19:05 +08:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
| Parameter | Description |
|
|
|
|
|
|------------------|------------------------------|
|
|
|
|
|
| spi_dev | SPI device structure pointer |
|
2024-01-31 22:45:56 +08:00
|
|
|
| path | Device path |
|
2023-12-28 01:19:05 +08:00
|
|
|
| cs_pin | Chip select pin number |
|
|
|
|
|
| cs_active | Chip select enable state |
|
|
|
|
|
| **Return Value** | |
|
|
|
|
|
| `=0` | Registration succeeded |
|
|
|
|
|
| `<0` | Error code |
|
|
|
|
|
|
2024-01-31 22:45:56 +08:00
|
|
|
- `path`: The SPI device needs to be bound to a specified SPI bus, and the path needs to add the bus name, such
|
|
|
|
|
as: `spix/dev-name`, `spi1/spi10`.
|
2023-12-28 01:19:05 +08:00
|
|
|
- `cs_pin`: Chip select pin number (refer to PIN device documentation).
|
|
|
|
|
- `cs_active`: Chip select enable state:
|
|
|
|
|
- `MR_SPI_CS_ACTIVE_LOW`: Low level enables.
|
|
|
|
|
- `MR_SPI_CS_ACTIVE_HIGH`: High level enables.
|
2024-01-31 22:45:56 +08:00
|
|
|
- `MR_SPI_CS_ACTIVE_HARDWARE`: Do not enable (Slave mode can only be used in this mode, and `cs_pin` will automatically be set to `-1`).
|
2023-12-28 01:19:05 +08:00
|
|
|
|
|
|
|
|
## Open SPI Device
|
|
|
|
|
|
|
|
|
|
```c
|
2024-01-31 22:45:56 +08:00
|
|
|
int mr_dev_open(const char *path, int flags);
|
2023-12-28 01:19:05 +08:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
| Parameter | Description |
|
|
|
|
|
|------------------|------------------------------|
|
2024-01-31 22:45:56 +08:00
|
|
|
| path | Device path |
|
|
|
|
|
| flags | Flags for opening the device |
|
2023-12-28 01:19:05 +08:00
|
|
|
| **Return Value** | |
|
|
|
|
|
| `>=0` | Device descriptor |
|
|
|
|
|
| `<0` | Error code |
|
|
|
|
|
|
2024-01-31 22:45:56 +08:00
|
|
|
- `path`: The SPI device is bound to the SPI bus, so the bus path needs to be added, such
|
|
|
|
|
as: `spix/dev-name`, `spi1/spi10`.
|
|
|
|
|
- `flags`: Flags for opening the device, supporting `MR_O_RDONLY`, `MR_O_WRONLY`, `MR_O_RDWR`.
|
2023-12-28 01:19:05 +08:00
|
|
|
|
|
|
|
|
Note: When using, different tasks should open the SPI device separately according to actual situations and use
|
2024-01-31 22:45:56 +08:00
|
|
|
appropriate `flags` for management and permission control to ensure they do not interfere with each other.
|
2023-12-28 01:19:05 +08:00
|
|
|
|
|
|
|
|
## Close SPI Device
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
int mr_dev_close(int desc);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
| Parameter | Description |
|
|
|
|
|
|------------------|---------------------|
|
|
|
|
|
| desc | Device descriptor |
|
|
|
|
|
| **Return Value** | |
|
|
|
|
|
| `=0` | Closed successfully |
|
|
|
|
|
| `<0` | Error code |
|
|
|
|
|
|
|
|
|
|
## Control SPI Device
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
int mr_dev_ioctl(int desc, int cmd, void *args);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
| Parameter | Description |
|
|
|
|
|
|------------------|-------------------|
|
|
|
|
|
| desc | Device descriptor |
|
|
|
|
|
| cmd | Command code |
|
|
|
|
|
| args | Command parameter |
|
|
|
|
|
| **Return Value** | |
|
|
|
|
|
| `=0` | Setting succeeded |
|
|
|
|
|
| `<0` | Error code |
|
|
|
|
|
|
|
|
|
|
- `cmd`: Command code, supports:
|
2024-01-31 22:45:56 +08:00
|
|
|
- `MR_IOC_SPI_SET_CONFIG`: Set SPI device configuration.
|
|
|
|
|
- `MR_IOC_SPI_SET_REG`: Set register value.
|
|
|
|
|
- `MR_IOC_SPI_SET_RD_BUFSZ`: Set read buffer size.
|
|
|
|
|
- `MR_IOC_SPI_CLR_RD_BUF`: Clear read buffer.
|
|
|
|
|
- `MR_IOC_SPI_SET_RD_CALL`: Set read callback function.
|
|
|
|
|
- `MR_IOC_SPI_TRANSFER`: Full-duplex transmission.
|
|
|
|
|
- `MR_IOC_SPI_GET_CONFIG`: Get SPI device configuration.
|
|
|
|
|
- `MR_IOC_SPI_GET_REG`: Get register value.
|
|
|
|
|
- `MR_IOC_SPI_GET_RD_BUFSZ`: Get read buffer size.
|
|
|
|
|
- `MR_IOC_SPI_GET_RD_DATASZ`: Get read buffer data size.
|
|
|
|
|
- `MR_IOC_SPI_GET_RD_CALL`: Get read callback function.
|
2023-12-28 01:19:05 +08:00
|
|
|
|
|
|
|
|
### Set/Get SPI Device Configuration
|
|
|
|
|
|
|
|
|
|
SPI device configuration:
|
|
|
|
|
|
|
|
|
|
- `baud_rate`: Baud rate.
|
|
|
|
|
- `host_slave`: Host/slave mode.
|
|
|
|
|
- `mode`: Mode.
|
|
|
|
|
- `data_bits`: Data bits.
|
|
|
|
|
- `bit_order`: Data transmission order.
|
|
|
|
|
- `reg_bits`: Register bits.
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
/* Set default configuration */
|
|
|
|
|
struct mr_spi_config config = MR_SPI_CONFIG_DEFAULT;
|
|
|
|
|
|
|
|
|
|
/* Set SPI device configuration */
|
2024-01-31 22:45:56 +08:00
|
|
|
mr_dev_ioctl(ds, MR_IOC_SPI_SET_CONFIG, &config);
|
2023-12-28 01:19:05 +08:00
|
|
|
|
|
|
|
|
/* Get SPI device configuration */
|
2024-01-31 22:45:56 +08:00
|
|
|
mr_dev_ioctl(ds, MR_IOC_SPI_GET_CONFIG, &config);
|
2023-12-28 01:19:05 +08:00
|
|
|
```
|
|
|
|
|
|
2024-01-18 03:29:46 +08:00
|
|
|
Independent of SPI interface:
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
/* Set default configuration */
|
|
|
|
|
int config[] = {3000000, 0, 0, 8, 1, 8};
|
|
|
|
|
|
|
|
|
|
/* Set SPI device configuration */
|
2024-01-31 22:45:56 +08:00
|
|
|
mr_dev_ioctl(ds, MR_IOC_SCFG, &config);
|
2024-01-18 03:29:46 +08:00
|
|
|
|
|
|
|
|
/* Get SPI device configuration */
|
2024-01-31 22:45:56 +08:00
|
|
|
mr_dev_ioctl(ds, MR_IOC_GCFG, &config);
|
2024-01-18 03:29:46 +08:00
|
|
|
```
|
|
|
|
|
|
2023-12-28 01:19:05 +08:00
|
|
|
Note:
|
|
|
|
|
|
|
|
|
|
- If not configured manually, the default configuration is:
|
|
|
|
|
- Baud rate: `3000000`
|
|
|
|
|
- Host/slave mode: `MR_SPI_HOST`
|
|
|
|
|
- Mode: `MR_SPI_MODE_0`
|
|
|
|
|
- Data bits: `MR_SPI_DATA_BITS_8`
|
|
|
|
|
- Data transmission order: `MR_SPI_BIT_ORDER_MSB`
|
|
|
|
|
- Register bits: `MR_SPI_REG_BITS_8`
|
|
|
|
|
- When an SPI device on the SPI bus is configured as slave mode, it will continuously occupy the SPI bus until the slave
|
|
|
|
|
mode SPI device is reconfigured to master mode. Other SPI devices cannot perform read/write operations during this
|
|
|
|
|
time.
|
2024-01-31 22:45:56 +08:00
|
|
|
- When hardware CS is forced to be used in slave mode, software IO will be restored to the default mode. For example,
|
|
|
|
|
to determine the use of slave mode at the beginning, set `cs_pin` to `-1` and `cs_active` to `MR_SPI_CS_ACTIVE_HARDWARE`.
|
2023-12-28 01:19:05 +08:00
|
|
|
|
|
|
|
|
### Set/Get Register Value
|
|
|
|
|
|
|
|
|
|
The register value will be written first (range: `0` ~ `INT32_MAX`) before reading and writing data.
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
/* Set register value */
|
2024-01-31 22:45:56 +08:00
|
|
|
mr_dev_ioctl(ds, MR_IOC_SPI_SET_REG, MR_MAKE_LOCAL(int, 0x12));
|
2023-12-28 01:19:05 +08:00
|
|
|
|
|
|
|
|
/* Get register value */
|
|
|
|
|
uint8_t reg;
|
2024-01-31 22:45:56 +08:00
|
|
|
mr_dev_ioctl(ds, MR_IOC_SPI_GET_REG, ®);
|
2023-12-28 01:19:05 +08:00
|
|
|
```
|
|
|
|
|
|
2024-01-18 03:29:46 +08:00
|
|
|
Independent of SPI interface:
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
/* Set register value */
|
2024-01-31 22:45:56 +08:00
|
|
|
mr_dev_ioctl(ds, MR_IOC_SPOS, MR_MAKE_LOCAL(int, 0x12));
|
2024-01-18 03:29:46 +08:00
|
|
|
|
|
|
|
|
/* Get register value */
|
|
|
|
|
uint8_t reg;
|
2024-01-31 22:45:56 +08:00
|
|
|
mr_dev_ioctl(ds, MR_IOC_GPOS, ®);
|
2024-01-18 03:29:46 +08:00
|
|
|
```
|
|
|
|
|
|
2023-12-28 01:19:05 +08:00
|
|
|
Note:
|
|
|
|
|
|
|
|
|
|
- The register value is only effective in master mode.
|
|
|
|
|
- Not effective if set to negative number.
|
|
|
|
|
- Register value not included in read/write size.
|
|
|
|
|
|
|
|
|
|
### Set/Get Read Buffer Size
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
size_t size = 256;
|
|
|
|
|
|
|
|
|
|
/* Set read buffer size */
|
2024-01-31 22:45:56 +08:00
|
|
|
mr_dev_ioctl(ds, MR_IOC_SPI_SET_RD_BUFSZ, &size);
|
2023-12-28 01:19:05 +08:00
|
|
|
|
|
|
|
|
/* Get read buffer size */
|
2024-01-31 22:45:56 +08:00
|
|
|
mr_dev_ioctl(ds, MR_IOC_SPI_GET_RD_BUFSZ, &size);
|
2023-12-28 01:19:05 +08:00
|
|
|
```
|
|
|
|
|
|
2024-01-18 03:29:46 +08:00
|
|
|
Independent of SPI interface:
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
size_t size = 256;
|
|
|
|
|
|
|
|
|
|
/* Set read buffer size */
|
2024-01-31 22:45:56 +08:00
|
|
|
mr_dev_ioctl(ds, MR_IOC_SRBSZ, &size);
|
2024-01-18 03:29:46 +08:00
|
|
|
|
|
|
|
|
/* Get read buffer size */
|
2024-01-31 22:45:56 +08:00
|
|
|
mr_dev_ioctl(ds, MR_IOC_GRBSZ, &size);
|
2024-01-18 03:29:46 +08:00
|
|
|
```
|
|
|
|
|
|
2023-12-28 01:19:05 +08:00
|
|
|
Note: If not set manually, it will use the size configured in `Kconfig` (default 32Byte). The read buffer is only used
|
|
|
|
|
in slave mode.
|
|
|
|
|
|
|
|
|
|
### Clear Read Buffer
|
|
|
|
|
|
|
|
|
|
```c
|
2024-01-31 22:45:56 +08:00
|
|
|
mr_dev_ioctl(ds, MR_IOC_SPI_CLR_RD_BUF, MR_NULL);
|
2023-12-28 01:19:05 +08:00
|
|
|
```
|
|
|
|
|
|
2024-01-18 03:29:46 +08:00
|
|
|
Independent of SPI interface:
|
|
|
|
|
|
|
|
|
|
```c
|
2024-01-31 22:45:56 +08:00
|
|
|
mr_dev_ioctl(ds, MR_IOC_CRBD, MR_NULL);
|
2024-01-18 03:29:46 +08:00
|
|
|
```
|
|
|
|
|
|
2023-12-28 01:19:05 +08:00
|
|
|
### Get Read Buffer Data Size
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
size_t size = 0;
|
|
|
|
|
|
|
|
|
|
/* Get read buffer data size */
|
2024-01-31 22:45:56 +08:00
|
|
|
mr_dev_ioctl(ds, MR_IOC_SPI_GET_RD_DATASZ, &size);
|
2023-12-28 01:19:05 +08:00
|
|
|
```
|
|
|
|
|
|
2024-01-18 03:29:46 +08:00
|
|
|
Independent of SPI interface:
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
size_t size = 0;
|
|
|
|
|
|
|
|
|
|
/* Get read buffer data size */
|
2024-01-31 22:45:56 +08:00
|
|
|
mr_dev_ioctl(ds, MR_IOC_GRBDSZ, &size);
|
2024-01-18 03:29:46 +08:00
|
|
|
```
|
|
|
|
|
|
2023-12-28 01:19:05 +08:00
|
|
|
### Set/Get Read Callback Function
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
/* Define callback function */
|
2024-01-31 22:45:56 +08:00
|
|
|
void fn(int desc, void *args)
|
2023-12-28 01:19:05 +08:00
|
|
|
{
|
|
|
|
|
/* Get buffer data size */
|
|
|
|
|
ssize_t data_size = *(ssize_t *)args;
|
|
|
|
|
|
|
|
|
|
/* Handle interrupt */
|
|
|
|
|
}
|
2024-01-31 22:45:56 +08:00
|
|
|
void (*callback)(int, void *args);
|
2023-12-28 01:19:05 +08:00
|
|
|
|
|
|
|
|
/* Set read callback function */
|
2024-01-31 22:45:56 +08:00
|
|
|
mr_dev_ioctl(ds, MR_IOC_SPI_SET_RD_CALL, &fn);
|
2023-12-28 01:19:05 +08:00
|
|
|
|
|
|
|
|
/* Get read callback function */
|
2024-01-31 22:45:56 +08:00
|
|
|
mr_dev_ioctl(ds, MR_IOC_SPI_GET_RD_CALL, &callback);
|
2023-12-28 01:19:05 +08:00
|
|
|
```
|
|
|
|
|
|
2024-01-18 03:29:46 +08:00
|
|
|
Independent of SPI interface:
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
/* Define callback function */
|
2024-01-31 22:45:56 +08:00
|
|
|
void fn(int desc, void *args)
|
2024-01-18 03:29:46 +08:00
|
|
|
{
|
|
|
|
|
/* Get buffer data size */
|
|
|
|
|
ssize_t data_size = *(ssize_t *)args;
|
|
|
|
|
|
|
|
|
|
/* Handle interrupt */
|
|
|
|
|
}
|
2024-01-31 22:45:56 +08:00
|
|
|
void (*callback)(int, void *args);
|
2024-01-18 03:29:46 +08:00
|
|
|
|
|
|
|
|
/* Set read callback function */
|
2024-01-31 22:45:56 +08:00
|
|
|
mr_dev_ioctl(ds, MR_IOC_SRCB, &fn);
|
2024-01-18 03:29:46 +08:00
|
|
|
|
|
|
|
|
/* Get read callback function */
|
2024-01-31 22:45:56 +08:00
|
|
|
mr_dev_ioctl(ds, MR_IOC_GRCB, &callback);
|
2024-01-18 03:29:46 +08:00
|
|
|
```
|
|
|
|
|
|
2023-12-28 01:19:05 +08:00
|
|
|
### Full-Duplex Transmission
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
/* Define transfer structure */
|
|
|
|
|
uint8_t buf[] = {0x01, 0x02, 0x03, 0x04};
|
|
|
|
|
struct mr_spi_transfer transfer =
|
|
|
|
|
{
|
|
|
|
|
.rd_buf = buf,
|
|
|
|
|
.wr_buf = buf,
|
|
|
|
|
.size = sizeof(buf),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* Full-duplex transmission */
|
2024-01-31 22:45:56 +08:00
|
|
|
ssize_t size = mr_dev_ioctl(ds, MR_IOC_SPI_TRANSFER, &transfer);
|
2023-12-28 01:19:05 +08:00
|
|
|
|
|
|
|
|
/* Check if transmission succeeded */
|
|
|
|
|
if (size < 0)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2024-01-18 03:29:46 +08:00
|
|
|
Independent of SPI interface:
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
/* Define transfer structure */
|
|
|
|
|
uint8_t buf[] = {0x01, 0x02, 0x03, 0x04};
|
|
|
|
|
struct
|
|
|
|
|
{
|
|
|
|
|
void *rd_buf;
|
|
|
|
|
const void *wr_buf;
|
|
|
|
|
size_t size;
|
|
|
|
|
} transfer = {buf, buf, sizeof(buf)};
|
|
|
|
|
|
|
|
|
|
/* Full-duplex transmission */
|
2024-01-31 22:45:56 +08:00
|
|
|
ssize_t size = mr_dev_ioctl(ds, (0x01), &transfer);
|
2024-01-18 03:29:46 +08:00
|
|
|
|
|
|
|
|
/* Check if transmission succeeded */
|
|
|
|
|
if (size < 0)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2023-12-28 01:19:05 +08:00
|
|
|
## Read SPI Device Data
|
|
|
|
|
|
|
|
|
|
```c
|
2024-01-31 22:45:56 +08:00
|
|
|
ssize_t mr_dev_read(int desc, void *buf, size_t count);
|
2023-12-28 01:19:05 +08:00
|
|
|
```
|
|
|
|
|
|
2024-02-02 16:38:44 +08:00
|
|
|
| Parameter | Description |
|
|
|
|
|
|------------------|-------------------|
|
|
|
|
|
| desc | Device descriptor |
|
|
|
|
|
| buf | Read data buffer |
|
|
|
|
|
| count | Read data size |
|
|
|
|
|
| **Return Value** | |
|
|
|
|
|
| `>=0` | Size of data read |
|
|
|
|
|
| `<0` | Error code |
|
2023-12-28 01:19:05 +08:00
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
uint8_t buf[128];
|
|
|
|
|
|
|
|
|
|
/* Read SPI device data */
|
|
|
|
|
ssize_t size = mr_dev_read(ds, buf, sizeof(buf));
|
|
|
|
|
|
|
|
|
|
/* Check if read succeeded */
|
|
|
|
|
if (size < 0)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Note:
|
|
|
|
|
|
2024-02-02 16:38:44 +08:00
|
|
|
- In master mode, polling will be used for synchronous reading. In slave mode,
|
|
|
|
|
reads a specified amount of data from the read buffer (returns the size of the data actually read).
|
2023-12-28 01:19:05 +08:00
|
|
|
- The register value writing will be inserted before the reading operation if the register parameter is not negative.
|
|
|
|
|
|
|
|
|
|
## Write SPI Device Data
|
|
|
|
|
|
|
|
|
|
```c
|
2024-01-31 22:45:56 +08:00
|
|
|
ssize_t mr_dev_write(int desc, const void *buf, size_t count);
|
2023-12-28 01:19:05 +08:00
|
|
|
```
|
|
|
|
|
|
2024-02-02 16:38:44 +08:00
|
|
|
| Parameter | Description |
|
|
|
|
|
|------------------|----------------------|
|
|
|
|
|
| desc | Device descriptor |
|
|
|
|
|
| buf | Write data buffer |
|
|
|
|
|
| count | Write data size |
|
|
|
|
|
| **Return Value** | |
|
|
|
|
|
| `>=0` | Size of data written |
|
|
|
|
|
| `<0` | Error code |
|
2023-12-28 01:19:05 +08:00
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
uint8_t buf[] = {0x01, 0x02, 0x03, 0x04};
|
|
|
|
|
|
|
|
|
|
/* Write SPI device data */
|
|
|
|
|
ssize_t size = mr_dev_write(ds, buf, sizeof(buf));
|
|
|
|
|
|
|
|
|
|
/* Check if write succeeded */
|
|
|
|
|
if (size < 0)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Note: The register value writing will be inserted before the writing operation if the register parameter is not
|
|
|
|
|
negative.
|
|
|
|
|
|
|
|
|
|
## Usage Example:
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
#include "include/mr_lib.h"
|
|
|
|
|
|
|
|
|
|
/* Define SPI devices */
|
|
|
|
|
struct mr_spi_dev host_dev;
|
|
|
|
|
struct mr_spi_dev slave_dev;
|
|
|
|
|
|
|
|
|
|
/* Define SPI device descriptors */
|
|
|
|
|
int host_ds = -1;
|
|
|
|
|
int slave_ds = -1;
|
|
|
|
|
|
2024-01-31 22:45:56 +08:00
|
|
|
void spi_init(void)
|
2023-12-28 01:19:05 +08:00
|
|
|
{
|
|
|
|
|
int ret = MR_EOK;
|
|
|
|
|
|
|
|
|
|
/* Register HOST SPI device */
|
|
|
|
|
ret = mr_spi_dev_register(&host_dev, "spi1/host", 0, MR_SPI_CS_ACTIVE_LOW);
|
|
|
|
|
if (ret < 0)
|
|
|
|
|
{
|
2024-01-31 22:45:56 +08:00
|
|
|
mr_printf("host spi device register failed: %d\r\n", mr_strerror(ret));
|
|
|
|
|
return;
|
2023-12-28 01:19:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Register SLAVE SPI device */
|
|
|
|
|
ret = mr_spi_dev_register(&slave_dev, "spi2/slave", 1, MR_SPI_CS_ACTIVE_LOW);
|
|
|
|
|
if (ret < 0)
|
|
|
|
|
{
|
2024-01-31 22:45:56 +08:00
|
|
|
mr_printf("slave spi device register failed: %d\r\n", mr_strerror(ret));
|
|
|
|
|
return;
|
2023-12-28 01:19:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Open HOST SPI device */
|
2024-01-31 22:45:56 +08:00
|
|
|
host_ds = mr_dev_open("spi1/host", MR_O_RDWR);
|
2023-12-28 01:19:05 +08:00
|
|
|
if (host_ds < 0)
|
|
|
|
|
{
|
2024-01-31 22:45:56 +08:00
|
|
|
mr_printf("host spi device open failed: %d\r\n", mr_strerror(ret));
|
|
|
|
|
return;
|
2023-12-28 01:19:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Set register value */
|
2024-01-31 22:45:56 +08:00
|
|
|
mr_dev_ioctl(host_ds, MR_IOC_SPI_SET_REG, MR_MAKE_LOCAL(int, 0x12));
|
2023-12-28 01:19:05 +08:00
|
|
|
|
|
|
|
|
/* Open SLAVE SPI device */
|
2024-01-31 22:45:56 +08:00
|
|
|
slave_ds = mr_dev_open("spi2/slave", MR_O_RDWR);
|
2023-12-28 01:19:05 +08:00
|
|
|
if (slave_ds < 0)
|
|
|
|
|
{
|
2024-01-31 22:45:56 +08:00
|
|
|
mr_printf("slave spi device open failed: %d\r\n", mr_strerror(ret));
|
|
|
|
|
return;
|
2023-12-28 01:19:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Set slave mode */
|
|
|
|
|
struct mr_spi_config config = MR_SPI_CONFIG_DEFAULT;
|
|
|
|
|
config.host_slave = MR_SPI_SLAVE;
|
2024-01-31 22:45:56 +08:00
|
|
|
ret = mr_dev_ioctl(slave_ds, MR_IOC_SPI_SET_CONFIG, &config);
|
2023-12-28 01:19:05 +08:00
|
|
|
if (ret < 0)
|
|
|
|
|
{
|
2024-01-31 22:45:56 +08:00
|
|
|
mr_printf("slave spi device set config failed: %d\r\n", mr_strerror(ret));
|
2023-12-28 01:19:05 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* Export to auto init (APP level) */
|
2023-12-30 03:29:01 +08:00
|
|
|
MR_INIT_APP_EXPORT(spi_init);
|
2023-12-28 01:19:05 +08:00
|
|
|
|
|
|
|
|
int main(void)
|
|
|
|
|
{
|
|
|
|
|
/* Auto init (spi_init function will be automatically called here) */
|
|
|
|
|
mr_auto_init();
|
|
|
|
|
|
|
|
|
|
/* Send test data */
|
|
|
|
|
uint8_t wr_buf[] = {0x01, 0x02, 0x03, 0x04};
|
|
|
|
|
mr_dev_write(host_ds, wr_buf, sizeof(wr_buf));
|
|
|
|
|
|
|
|
|
|
/* Receive test data */
|
|
|
|
|
uint8_t rd_buf[128];
|
2024-01-31 22:45:56 +08:00
|
|
|
mr_dev_read(slave_ds, rd_buf, sizeof(rd_buf));
|
2023-12-28 01:19:05 +08:00
|
|
|
|
|
|
|
|
/* Compare register value */
|
|
|
|
|
if (rd_buf[0] == 0x12)
|
|
|
|
|
{
|
2024-01-31 22:45:56 +08:00
|
|
|
/* Compare data */
|
|
|
|
|
if (memcmp(wr_buf, (rd_buf + 1), sizeof(wr_buf)) == 0)
|
|
|
|
|
{
|
|
|
|
|
mr_printf("spi test success\r\n");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2023-12-28 01:19:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (1)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Connect SPI1 and SPI2, with pin 0 and 1 connected (refer to PIN device documentation), to perform send and receive test.
|
|
|
|
|
SPI1 acts as master and SPI2 acts as slave. SPI2 will compare the received data with the sent data.
|
|
|
|
|
Since the register value is set, the register value is received first before the written data.
|