1.优化spi架构,完善总线多模式复用。

This commit is contained in:
MacRsh
2023-07-30 22:18:35 +08:00
parent 501faeca5e
commit 25f2809cf5
2 changed files with 122 additions and 113 deletions

View File

@@ -10,14 +10,12 @@
#include "device/spi/spi.h"
#if (MR_CONF_PIN == MR_CONF_ENABLE)
#include "device/pin/pin.h"
#endif /* MR_CONF_PIN */
#if (MR_CONF_SPI == MR_CONF_ENABLE)
#if (MR_CONF_PIN == MR_CONF_ENABLE)
#include "device/pin/pin.h"
#endif
mr_inline mr_err_t mr_spi_device_take_bus(mr_spi_device_t spi_device)
{
mr_err_t ret = MR_ERR_OK;
@@ -25,7 +23,7 @@ mr_inline mr_err_t mr_spi_device_take_bus(mr_spi_device_t spi_device)
/* Without attach the bus */
if (spi_device->bus == MR_NULL)
{
return -MR_ERR_GENERIC;
return -MR_ERR_NOT_FOUND;
}
/* Take the mutex lock of the spi-bus */
@@ -66,7 +64,7 @@ mr_inline mr_err_t mr_spi_device_release_bus(mr_spi_device_t spi_device)
/* Without attach the bus */
if (spi_device->bus == MR_NULL)
{
return -MR_ERR_GENERIC;
return -MR_ERR_NOT_FOUND;
}
/* Release the mutex lock of the spi-bus */
@@ -90,20 +88,41 @@ mr_inline mr_uint8_t mr_spi_device_transfer(mr_spi_device_t spi_device, mr_uint8
static mr_err_t mr_spi_device_open(mr_device_t device)
{
mr_spi_device_t spi_device = (mr_spi_device_t)device;
struct mr_spi_config default_config = MR_SPI_CONFIG_DEFAULT;
#if (MR_CONF_PIN == MR_CONF_ENABLE)
struct mr_pin_config pin_config = {spi_device->cs_number, MR_PIN_MODE_OUTPUT};
mr_device_t pin = MR_NULL;
#endif
/* Setting spi-device to default config, if the baud-rate not set */
if (spi_device->config.baud_rate == 0)
{
struct mr_spi_config default_config = MR_SPI_CONFIG_DEFAULT;
spi_device->config = default_config;
}
#if (MR_CONF_PIN == MR_CONF_ENABLE)
/* Configure pin */
if (spi_device->config.cs_active != MR_SPI_CS_ACTIVE_NONE)
{
pin = mr_device_find("pin");
if (pin != MR_NULL)
{
mr_device_open(pin, MR_OPEN_RDWR);
mr_device_ioctl(pin, MR_CTRL_SET_CONFIG, &pin_config);
}
}
#endif
return MR_ERR_OK;
}
static mr_err_t mr_spi_device_close(mr_device_t device)
{
mr_spi_device_t spi_device = (mr_spi_device_t)device;
#if (MR_CONF_PIN == MR_CONF_ENABLE)
struct mr_pin_config pin_config = {spi_device->cs_number, MR_PIN_MODE_NONE};
mr_device_t pin = MR_NULL;
#endif
/* Setting spi-device to close config */
spi_device->config.baud_rate = 0;
@@ -111,15 +130,25 @@ static mr_err_t mr_spi_device_close(mr_device_t device)
/* Disconnect from the spi-bus */
spi_device->bus = MR_NULL;
#if (MR_CONF_PIN == MR_CONF_ENABLE)
/* Configure pin */
if (spi_device->config.cs_active != MR_SPI_CS_ACTIVE_NONE)
{
pin = mr_device_find("pin");
if (pin != MR_NULL)
{
mr_device_ioctl(pin, MR_CTRL_SET_CONFIG, &pin_config);
mr_device_close(pin);
}
}
#endif
return MR_ERR_OK;
}
static mr_err_t mr_spi_device_ioctl(mr_device_t device, int cmd, void *args)
{
mr_spi_device_t spi_device = (mr_spi_device_t)device;
struct mr_spi_config *config = MR_NULL;
mr_uint8_t *buffer = MR_NULL;
mr_size_t transfer_size = 0;
mr_err_t ret = MR_ERR_OK;
switch (cmd & _MR_CTRL_FLAG_MASK)
@@ -128,7 +157,7 @@ static mr_err_t mr_spi_device_ioctl(mr_device_t device, int cmd, void *args)
{
if (args)
{
config = (struct mr_spi_config *)args;
struct mr_spi_config *config = (struct mr_spi_config *)args;
spi_device->config = *config;
return MR_ERR_OK;
}
@@ -139,7 +168,7 @@ static mr_err_t mr_spi_device_ioctl(mr_device_t device, int cmd, void *args)
{
if (args)
{
config = (struct mr_spi_config *)args;
struct mr_spi_config *config = (struct mr_spi_config *)args;
*config = spi_device->config;
return MR_ERR_OK;
}
@@ -171,8 +200,8 @@ static mr_err_t mr_spi_device_ioctl(mr_device_t device, int cmd, void *args)
{
return ret;
}
spi_device->bus = MR_NULL;
}
spi_device->bus = MR_NULL;
return MR_ERR_OK;
}
@@ -204,15 +233,18 @@ static mr_err_t mr_spi_device_ioctl(mr_device_t device, int cmd, void *args)
return ret;
}
/* Wait bus free */
while (mr_list_is_empty(&spi_device->bus->tx_list) != MR_TRUE);
do
{
buffer = (mr_uint8_t *)((mr_transfer_t)args)->data;
mr_uint8_t *transfer_buffer = (mr_uint8_t *)((mr_transfer_t)args)->data;
mr_size_t transfer_size = ((mr_transfer_t)args)->size;
for (transfer_size = 0;
transfer_size < ((mr_transfer_t)args)->size; transfer_size += sizeof(*buffer))
while (transfer_size--)
{
*buffer = mr_spi_device_transfer(spi_device, *buffer);
buffer++;
*transfer_buffer = mr_spi_device_transfer(spi_device, *transfer_buffer);
transfer_buffer++;
}
/* Get the next transfer */
@@ -234,9 +266,9 @@ static mr_err_t mr_spi_device_ioctl(mr_device_t device, int cmd, void *args)
static mr_ssize_t mr_spi_device_read(mr_device_t device, mr_pos_t pos, void *buffer, mr_size_t size)
{
mr_spi_device_t spi_device = (mr_spi_device_t)device;
mr_uint8_t *recv_buffer = (mr_uint8_t *)buffer;
mr_uint8_t *read_buffer = (mr_uint8_t *)buffer;
mr_spi_bus_t spi_bus = MR_NULL;
mr_size_t recv_size = 0;
mr_size_t read_size = 0;
mr_err_t ret = MR_ERR_OK;
/* Take spi-bus */
@@ -247,60 +279,56 @@ static mr_ssize_t mr_spi_device_read(mr_device_t device, mr_pos_t pos, void *buf
}
spi_bus = spi_device->bus;
if (spi_device->config.host_slave == MR_SPI_HOST)
if (spi_bus->rx_fifo.bufsz == 0 || spi_device->config.host_slave == MR_SPI_HOST)
{
/* Start the chip-select of the current device */
spi_bus->ops->cs_ctrl(spi_bus, spi_device->cs_number, MR_ENABLE);
/* Wait bus free */
while (mr_list_is_empty(&spi_bus->tx_list) != MR_TRUE);
/* Send position */
if (pos != 0)
if (spi_device->config.host_slave == MR_SPI_HOST)
{
mr_spi_device_transfer(spi_device, (mr_uint8_t)pos);
/* Start the chip-select of the current device */
spi_bus->ops->cs_ctrl(spi_bus, spi_device->cs_number, MR_ENABLE);
/* Send position */
if (pos != 0)
{
mr_spi_device_transfer(spi_device, (mr_uint8_t)pos);
}
}
/* Blocking read */
for (recv_size = 0; recv_size < size; recv_size += sizeof(*recv_buffer))
for (read_size = 0; read_size < size; read_size += sizeof(*read_buffer))
{
*recv_buffer = mr_spi_device_transfer(spi_device, 0u);
recv_buffer++;
*read_buffer = mr_spi_device_transfer(spi_device, 0u);
read_buffer++;
}
/* Stop the chip-select of the current device */
spi_bus->ops->cs_ctrl(spi_bus, spi_device->cs_number, MR_DISABLE);
if (spi_device->config.host_slave == MR_SPI_HOST)
{
/* Stop the chip-select of the current device */
spi_bus->ops->cs_ctrl(spi_bus, spi_device->cs_number, MR_DISABLE);
}
} else
{
if (spi_bus->rx_fifo.bufsz == 0)
/* Non-blocking read */
for (read_size = 0; read_size < size;)
{
/* Blocking read */
for (recv_size = 0; recv_size < size; recv_size += sizeof(*recv_buffer))
{
*recv_buffer = mr_spi_device_transfer(spi_device, 0u);
recv_buffer++;
}
} else
{
/* Non-blocking read */
for (recv_size = 0; recv_size < size;)
{
recv_size += mr_fifo_read(&spi_bus->rx_fifo.fifo, recv_buffer + recv_size, size - recv_size);
}
read_size += mr_fifo_read(&spi_bus->rx_fifo.fifo, read_buffer + read_size, size - read_size);
}
}
/* Release spi-bus */
mr_spi_device_release_bus(spi_device);
return (mr_ssize_t)recv_size;
return (mr_ssize_t)read_size;
}
static mr_ssize_t mr_spi_device_write(mr_device_t device, mr_pos_t pos, const void *buffer, mr_size_t size)
{
mr_spi_device_t spi_device = (mr_spi_device_t)device;
mr_uint8_t *send_buffer = (mr_uint8_t *)buffer;
mr_uint8_t *write_buffer = (mr_uint8_t *)buffer;
mr_spi_bus_t spi_bus = MR_NULL;
mr_size_t send_size = 0;
mr_uint8_t send_position = 0;
mr_size_t dma_size = 0;
mr_size_t write_size = 0;
mr_err_t ret = MR_ERR_OK;
/* Take spi-bus */
@@ -313,6 +341,12 @@ static mr_ssize_t mr_spi_device_write(mr_device_t device, mr_pos_t pos, const vo
if (spi_bus->tx_fifo.bufsz == 0 || (spi_device->device.open_flag & MR_OPEN_NONBLOCKING) == 0)
{
if ((spi_device->device.open_flag & MR_OPEN_NONBLOCKING) == 0)
{
/* Wait bus free */
while (mr_list_is_empty(&spi_bus->tx_list) != MR_TRUE);
}
if (spi_device->config.host_slave == MR_SPI_HOST)
{
/* Start the chip-select of the current device */
@@ -326,10 +360,10 @@ static mr_ssize_t mr_spi_device_write(mr_device_t device, mr_pos_t pos, const vo
}
/* Blocking write */
for (send_size = 0; send_size < size; send_size += sizeof(*send_buffer))
for (write_size = 0; write_size < size; write_size += sizeof(*write_buffer))
{
mr_spi_device_transfer(spi_device, *send_buffer);
send_buffer++;
mr_spi_device_transfer(spi_device, *write_buffer);
write_buffer++;
}
/* Stop the chip-select of the current device */
@@ -344,31 +378,31 @@ static mr_ssize_t mr_spi_device_write(mr_device_t device, mr_pos_t pos, const vo
/* Send position */
if (pos != 0)
{
send_position = (mr_uint8_t)pos;
for (send_size = 0; send_size < sizeof(send_position);)
mr_uint8_t send_position = (mr_uint8_t)pos;
for (write_size = 0; write_size < sizeof(send_position);)
{
send_size += mr_fifo_write(&spi_bus->tx_fifo.fifo, &send_position, sizeof(send_position));
write_size += mr_fifo_write(&spi_bus->tx_fifo.fifo, &send_position, sizeof(send_position));
}
spi_device->tx_count += sizeof(send_position);
}
}
/* Count the number of send */
/* Insert the tx-list */
spi_device->tx_count += size;
if (mr_list_is_empty(&spi_device->tx_list))
if (mr_list_is_empty(&spi_device->tx_list) == MR_TRUE)
{
mr_list_insert_before(&spi_bus->tx_list, &spi_device->tx_list);
}
/* Non-blocking write */
for (send_size = 0; send_size < size;)
for (write_size = 0; write_size < size;)
{
/* If this is the first write, start sending */
if (mr_fifo_get_data_size(&spi_bus->tx_fifo.fifo) != 0)
{
send_size += mr_fifo_write(&spi_bus->tx_fifo.fifo, send_buffer + send_size, size - send_size);
write_size += mr_fifo_write(&spi_bus->tx_fifo.fifo, write_buffer + write_size, size - write_size);
} else
{
send_size += mr_fifo_write(&spi_bus->tx_fifo.fifo, send_buffer + send_size, size - send_size);
write_size += mr_fifo_write(&spi_bus->tx_fifo.fifo, write_buffer + write_size, size - write_size);
/* Start the chip-select of the current device */
if (spi_device->config.host_slave == MR_SPI_HOST)
@@ -383,9 +417,7 @@ static mr_ssize_t mr_spi_device_write(mr_device_t device, mr_pos_t pos, const vo
} else
{
/* DMA write */
dma_size = mr_fifo_read(&spi_bus->tx_fifo.fifo,
spi_bus->tx_dma,
sizeof(spi_bus->tx_dma));
mr_size_t dma_size = mr_fifo_read(&spi_bus->tx_fifo.fifo, spi_bus->tx_dma, sizeof(spi_bus->tx_dma));
spi_bus->ops->start_dma_tx(spi_bus, spi_bus->tx_dma, dma_size);
}
}
@@ -395,13 +427,11 @@ static mr_ssize_t mr_spi_device_write(mr_device_t device, mr_pos_t pos, const vo
/* Release spi-bus */
mr_spi_device_release_bus(spi_device);
return (mr_ssize_t)send_size;
return (mr_ssize_t)write_size;
}
static mr_err_t mr_spi_bus_rx_fifo_init(mr_spi_bus_t spi_bus, mr_size_t rx_bufsz)
{
mr_uint8_t *buffer = MR_NULL;
if (spi_bus->rx_fifo.fifo.buffer)
{
mr_free(spi_bus->rx_fifo.fifo.buffer);
@@ -412,7 +442,7 @@ static mr_err_t mr_spi_bus_rx_fifo_init(mr_spi_bus_t spi_bus, mr_size_t rx_bufsz
if (spi_bus->rx_fifo.bufsz != 0)
{
buffer = mr_malloc(spi_bus->rx_fifo.bufsz);
mr_uint8_t *buffer = mr_malloc(spi_bus->rx_fifo.bufsz);
if (buffer == MR_NULL)
{
return -MR_ERR_NO_MEMORY;
@@ -425,8 +455,6 @@ static mr_err_t mr_spi_bus_rx_fifo_init(mr_spi_bus_t spi_bus, mr_size_t rx_bufsz
static mr_err_t mr_spi_bus_tx_fifo_init(mr_spi_bus_t spi_bus, mr_size_t tx_bufsz)
{
mr_uint8_t *buffer = MR_NULL;
if (spi_bus->tx_fifo.fifo.buffer)
{
mr_free(spi_bus->tx_fifo.fifo.buffer);
@@ -437,7 +465,7 @@ static mr_err_t mr_spi_bus_tx_fifo_init(mr_spi_bus_t spi_bus, mr_size_t tx_bufsz
if (spi_bus->tx_fifo.bufsz != 0)
{
buffer = mr_malloc(spi_bus->tx_fifo.bufsz);
mr_uint8_t *buffer = mr_malloc(spi_bus->tx_fifo.bufsz);
if (buffer == MR_NULL)
{
return -MR_ERR_NO_MEMORY;
@@ -451,7 +479,6 @@ static mr_err_t mr_spi_bus_tx_fifo_init(mr_spi_bus_t spi_bus, mr_size_t tx_bufsz
static mr_err_t mr_spi_bus_open(mr_device_t device)
{
mr_spi_bus_t spi_bus = (mr_spi_bus_t)device;
struct mr_spi_config default_config = MR_SPI_CONFIG_DEFAULT;
mr_err_t ret = MR_ERR_OK;
/* Allocate the fifo buffer */
@@ -469,6 +496,7 @@ static mr_err_t mr_spi_bus_open(mr_device_t device)
/* Setting spi-bus to default config, if the baud-rate not set */
if (spi_bus->config.baud_rate == 0)
{
struct mr_spi_config default_config = MR_SPI_CONFIG_DEFAULT;
spi_bus->config = default_config;
}
@@ -610,7 +638,7 @@ mr_err_t mr_spi_bus_add(mr_spi_bus_t spi_bus, const char *name, void *data, stru
return mr_device_add(&spi_bus->device, name, MR_OPEN_RDWR);
}
mr_err_t mr_spi_device_add(mr_spi_device_t spi_device, const char *name, mr_uint16_t cs_pin)
mr_err_t mr_spi_device_add(mr_spi_device_t spi_device, const char *name, mr_pos_t cs_number)
{
const static struct mr_device_ops device_ops =
{
@@ -620,10 +648,6 @@ mr_err_t mr_spi_device_add(mr_spi_device_t spi_device, const char *name, mr_uint
mr_spi_device_read,
mr_spi_device_write,
};
#if (MR_CONF_PIN == MR_CONF_ENABLE)
struct mr_pin_config pin_config = {cs_pin, MR_PIN_MODE_OUTPUT};
mr_device_t pin = MR_NULL;
#endif /* MR_CONF_PIN */
MR_ASSERT(spi_device != MR_NULL);
MR_ASSERT(name != MR_NULL);
@@ -635,38 +659,23 @@ mr_err_t mr_spi_device_add(mr_spi_device_t spi_device, const char *name, mr_uint
spi_device->config.baud_rate = 0;
spi_device->bus = MR_NULL;
spi_device->cs_number = cs_pin;
spi_device->cs_number = cs_number;
mr_list_init(&spi_device->tx_list);
spi_device->tx_count = 0;
#if (MR_CONF_PIN == MR_CONF_ENABLE)
/* Configure pin */
pin = mr_device_find("pin");
if (pin == MR_NULL)
{
return -MR_ERR_NOT_FOUND;
}
mr_device_open(pin, MR_OPEN_RDWR);
mr_device_ioctl(pin, MR_CTRL_SET_CONFIG, &pin_config);
#endif /* MR_CONF_PIN */
/* Add to the container */
return mr_device_add(&spi_device->device, name, MR_OPEN_RDWR | MR_OPEN_NONBLOCKING);
}
void mr_spi_bus_isr(mr_spi_bus_t spi_bus, mr_uint32_t event)
{
mr_spi_device_t spi_device = MR_NULL;
mr_uint32_t length = 0;
mr_uint8_t data = 0;
MR_ASSERT(spi_bus != MR_NULL);
switch (event & _MR_SPI_BUS_EVENT_MASK)
{
case MR_SPI_BUS_EVENT_RX_INT:
{
spi_device = spi_bus->owner;
mr_spi_device_t spi_device = spi_bus->owner;
/* The data not belong to this device */
if (spi_device->config.host_slave == MR_SPI_HOST ||
@@ -676,13 +685,13 @@ void mr_spi_bus_isr(mr_spi_bus_t spi_bus, mr_uint32_t event)
}
/* Read data into the fifo */
data = spi_bus->ops->read(spi_bus);
mr_uint8_t data = spi_bus->ops->read(spi_bus);
mr_fifo_write_force(&spi_bus->rx_fifo.fifo, &data, sizeof(data));
/* Invoke the rx-cb function */
if (spi_device->device.rx_cb != MR_NULL)
{
length = mr_fifo_get_data_size(&spi_bus->rx_fifo.fifo);
mr_size_t length = mr_fifo_get_data_size(&spi_bus->rx_fifo.fifo);
spi_device->device.rx_cb(&spi_device->device, &length);
}
break;
@@ -690,10 +699,18 @@ void mr_spi_bus_isr(mr_spi_bus_t spi_bus, mr_uint32_t event)
case MR_SPI_BUS_EVENT_TX_INT:
{
/* Check if the list is not empty */
if (!mr_list_is_empty(&spi_bus->tx_list))
/* Write data from the fifo */
mr_uint8_t data = 0;
if (mr_fifo_read(&spi_bus->tx_fifo.fifo, &data, sizeof(data)) != 0)
{
spi_device = mr_container_of(spi_bus->tx_list.next, struct mr_spi_device, tx_list);
/* Get the tx device */
mr_spi_device_t spi_device = mr_container_of(spi_bus->tx_list.next, struct mr_spi_device, tx_list);
/* Transfer data */
mr_spi_device_transfer(spi_device, data);
/* Decrement tx count */
spi_device->tx_count--;
if (spi_device->tx_count == 0)
{
/* Remove from the list */
@@ -712,7 +729,7 @@ void mr_spi_bus_isr(mr_spi_bus_t spi_bus, mr_uint32_t event)
}
/* Select next device if list not empty */
if (!mr_list_is_empty(&spi_bus->tx_list))
if (mr_list_is_empty(&spi_bus->tx_list) != MR_TRUE)
{
spi_device = mr_container_of(spi_bus->tx_list.next, struct mr_spi_device, tx_list);
@@ -722,14 +739,6 @@ void mr_spi_bus_isr(mr_spi_bus_t spi_bus, mr_uint32_t event)
spi_bus->ops->cs_ctrl(spi_bus, spi_device->cs_number, MR_ENABLE);
}
}
} else
{
/* Decrement tx count */
spi_device->tx_count--;
/* Write data from the fifo */
mr_fifo_read(&spi_bus->tx_fifo.fifo, &data, sizeof(data));
mr_spi_device_transfer(spi_device, data);
}
} else
{

View File

@@ -52,7 +52,7 @@ struct mr_spi_config
mr_uint8_t host_slave: 1;
mr_uint8_t mode: 2;
mr_uint8_t bit_order: 1;
mr_uint8_t cs_active: 2;
mr_level_t cs_active: 2;
};
struct mr_spi_fifo
@@ -108,7 +108,7 @@ struct mr_spi_bus
};
mr_err_t mr_spi_bus_add(mr_spi_bus_t spi_bus, const char *name, void *data, struct mr_spi_bus_ops *ops);
mr_err_t mr_spi_device_add(mr_spi_device_t spi_device, const char *name, mr_uint16_t cs_pin);
mr_err_t mr_spi_device_add(mr_spi_device_t spi_device, const char *name, mr_pos_t cs_number);
void mr_spi_bus_isr(mr_spi_bus_t spi_bus, mr_uint32_t event);
#endif /* MR_CONF_SPI */