1.优化连接总线功能。优化从设备功能,从设备连接后将独占总线,其余设备不再允许任何读写总线操作直至从设备断开连接。

This commit is contained in:
MacRsh
2023-09-23 18:32:55 +08:00
parent 378354ec45
commit 1fb132d6cf
2 changed files with 169 additions and 144 deletions

View File

@@ -45,54 +45,6 @@ static mr_level_t err_io_spi_cs_read(mr_spi_bus_t spi_bus, mr_off_t cs_number)
return 0;
}
static mr_err_t mr_spi_device_connect_bus(mr_spi_device_t spi_device, const char *name)
{
mr_device_t spi_bus = MR_NULL;
mr_err_t ret = MR_ERR_OK;
/* Disconnect the spi-bus */
if (name == MR_NULL)
{
if (spi_device->bus != MR_NULL)
{
/* Get the spi-bus */
spi_bus = (mr_device_t)spi_device->bus;
/* Close the spi-bus */
ret = mr_device_close(spi_bus);
if (ret != MR_ERR_OK)
{
return ret;
}
spi_device->bus = MR_NULL;
spi_device->device.oflags = spi_device->device.sflags = MR_DEVICE_OFLAG_CLOSED;
}
return MR_ERR_OK;
}
/* Connect the spi-bus */
spi_bus = mr_device_find(name);
if (spi_bus == MR_NULL || spi_bus->type != Mr_Device_Type_SPIBUS)
{
return -MR_ERR_NOT_FOUND;
}
/* Open the spi-bus */
ret = mr_device_open(spi_bus, MR_DEVICE_OFLAG_RDWR);
if (ret != MR_ERR_OK)
{
return ret;
}
/* Set the spi-bus */
spi_device->bus = (mr_spi_bus_t)spi_bus;
spi_device->device.sflags = spi_bus->sflags;
return MR_ERR_OK;
}
mr_err_t mr_spi_device_take_bus(mr_spi_device_t spi_device)
{
mr_spi_bus_t spi_bus = (mr_spi_bus_t)spi_device->bus;
@@ -112,7 +64,7 @@ mr_err_t mr_spi_device_take_bus(mr_spi_device_t spi_device)
}
/* Check if the spi-bus owner is different from the current one */
if (spi_bus->owner != spi_device)
if (mr_mutex_get_owner(&spi_bus->lock) != spi_bus->owner)
{
/* If the configuration is different, the spi-bus is reconfigured */
if (spi_device->config.baud_rate != spi_bus->config.baud_rate
@@ -132,7 +84,7 @@ mr_err_t mr_spi_device_take_bus(mr_spi_device_t spi_device)
/* Sets the spi-bus owner to the current spi-device */
spi_bus->config = spi_device->config;
spi_bus->owner = spi_device;
spi_bus->owner = (mr_spi_device_t)mr_mutex_get_owner(&spi_bus->lock);
}
return MR_ERR_OK;
@@ -146,6 +98,62 @@ static mr_err_t mr_spi_device_release_bus(mr_spi_device_t spi_device)
return mr_mutex_release(&spi_bus->lock, spi_device);
}
static mr_err_t mr_spi_device_connect_bus(mr_spi_device_t spi_device, const char *name)
{
mr_device_t spi_bus = MR_NULL;
mr_err_t ret = MR_ERR_OK;
if (name != MR_NULL)
{
/* Connect the spi-bus */
spi_bus = mr_device_find(name);
if (spi_bus == MR_NULL || spi_bus->type != Mr_Device_Type_SPIBUS)
{
return -MR_ERR_NOT_FOUND;
}
}
if (spi_bus != (mr_device_t)spi_device->bus)
{
/* Disconnect the old spi-bus */
if (spi_device->bus != MR_NULL)
{
/* Release the mutex */
if (spi_device->config.host_slave == MR_SPI_SLAVE)
{
mr_spi_device_release_bus(spi_device);
}
/* Close the spi-bus */
ret = mr_device_close((mr_device_t)spi_device->bus);
if (ret != MR_ERR_OK)
{
return ret;
}
spi_device->bus = MR_NULL;
}
/* Set the spi-bus */
spi_device->bus = (mr_spi_bus_t)spi_bus;
/* Slave mode monopolizes the bus */
if (spi_device->config.host_slave == MR_SPI_SLAVE)
{
ret = mr_spi_device_take_bus(spi_device);
if (ret != MR_ERR_OK)
{
spi_device->bus = MR_NULL;
return ret;
}
}
/* Open the spi-bus */
return mr_device_open(spi_bus, MR_DEVICE_OFLAG_RDWR);
}
return MR_ERR_OK;
}
MR_INLINE void mr_spi_device_cs_set_state(mr_spi_device_t spi_device, mr_state_t state)
{
mr_spi_bus_t spi_bus = spi_device->bus;
@@ -168,13 +176,14 @@ MR_INLINE mr_state_t mr_spi_device_cs_get_state(mr_spi_device_t spi_device)
return MR_ENABLE;
}
static mr_ssize_t mr_spi_bus_transfer(mr_spi_bus_t spi_bus,
void *write_data,
void *read_data,
mr_size_t size,
mr_state_t rw)
static mr_ssize_t mr_spi_device_transfer(mr_spi_device_t spi_device,
void *write_data,
void *read_data,
mr_size_t size,
mr_state_t rw)
{
mr_size_t tran_size = 0;
mr_spi_bus_t spi_bus = spi_device->bus;
mr_size_t tf_size = 0;
if (rw == MR_SPI_WR)
{
@@ -183,7 +192,7 @@ static mr_ssize_t mr_spi_bus_transfer(mr_spi_bus_t spi_bus,
case MR_SPI_DATA_BITS_8:
{
mr_uint8_t *w_data = (mr_uint8_t *)write_data;
while ((tran_size += (sizeof(*w_data))) <= size)
while ((tf_size += (sizeof(*w_data))) <= size)
{
spi_bus->ops->write(spi_bus, *w_data);
spi_bus->ops->read(spi_bus);
@@ -195,7 +204,7 @@ static mr_ssize_t mr_spi_bus_transfer(mr_spi_bus_t spi_bus,
case MR_SPI_DATA_BITS_16:
{
mr_uint16_t *w_data = (mr_uint16_t *)write_data;
while ((tran_size += (sizeof(*w_data))) <= size)
while ((tf_size += (sizeof(*w_data))) <= size)
{
spi_bus->ops->write(spi_bus, *w_data);
spi_bus->ops->read(spi_bus);
@@ -207,7 +216,7 @@ static mr_ssize_t mr_spi_bus_transfer(mr_spi_bus_t spi_bus,
case MR_SPI_DATA_BITS_32:
{
mr_uint32_t *w_data = (mr_uint32_t *)write_data;
while ((tran_size += (sizeof(*w_data))) <= size)
while ((tf_size += (sizeof(*w_data))) <= size)
{
spi_bus->ops->write(spi_bus, *w_data);
spi_bus->ops->read(spi_bus);
@@ -226,7 +235,7 @@ static mr_ssize_t mr_spi_bus_transfer(mr_spi_bus_t spi_bus,
case MR_SPI_DATA_BITS_8:
{
mr_uint8_t *r_data = (mr_uint8_t *)read_data;
while ((tran_size += (sizeof(*r_data))) <= size)
while ((tf_size += (sizeof(*r_data))) <= size)
{
spi_bus->ops->write(spi_bus, 0);
*r_data = spi_bus->ops->read(spi_bus);
@@ -238,7 +247,7 @@ static mr_ssize_t mr_spi_bus_transfer(mr_spi_bus_t spi_bus,
case MR_SPI_DATA_BITS_16:
{
mr_uint16_t *r_data = (mr_uint16_t *)read_data;
while ((tran_size += (sizeof(*r_data))) <= size)
while ((tf_size += (sizeof(*r_data))) <= size)
{
spi_bus->ops->write(spi_bus, 0);
*r_data = spi_bus->ops->read(spi_bus);
@@ -250,7 +259,7 @@ static mr_ssize_t mr_spi_bus_transfer(mr_spi_bus_t spi_bus,
case MR_SPI_DATA_BITS_32:
{
mr_uint32_t *r_data = (mr_uint32_t *)read_data;
while ((tran_size += (sizeof(*r_data))) <= size)
while ((tf_size += (sizeof(*r_data))) <= size)
{
spi_bus->ops->write(spi_bus, 0);
*r_data = spi_bus->ops->read(spi_bus);
@@ -270,7 +279,7 @@ static mr_ssize_t mr_spi_bus_transfer(mr_spi_bus_t spi_bus,
{
mr_uint8_t *w_data = (mr_uint8_t *)write_data;
mr_uint8_t *r_data = (mr_uint8_t *)read_data;
while ((tran_size += (sizeof(*w_data))) <= size)
while ((tf_size += (sizeof(*w_data))) <= size)
{
spi_bus->ops->write(spi_bus, *w_data);
*r_data = spi_bus->ops->read(spi_bus);
@@ -283,7 +292,7 @@ static mr_ssize_t mr_spi_bus_transfer(mr_spi_bus_t spi_bus,
{
mr_uint16_t *w_data = (mr_uint16_t *)write_data;
mr_uint16_t *r_data = (mr_uint16_t *)read_data;
while ((tran_size += (sizeof(*w_data))) <= size)
while ((tf_size += (sizeof(*w_data))) <= size)
{
spi_bus->ops->write(spi_bus, *w_data);
*r_data = spi_bus->ops->read(spi_bus);
@@ -296,7 +305,7 @@ static mr_ssize_t mr_spi_bus_transfer(mr_spi_bus_t spi_bus,
{
mr_uint32_t *w_data = (mr_uint32_t *)write_data;
mr_uint32_t *r_data = (mr_uint32_t *)read_data;
while ((tran_size += (sizeof(*w_data))) <= size)
while ((tf_size += (sizeof(*w_data))) <= size)
{
spi_bus->ops->write(spi_bus, *w_data);
*r_data = spi_bus->ops->read(spi_bus);
@@ -310,7 +319,7 @@ static mr_ssize_t mr_spi_bus_transfer(mr_spi_bus_t spi_bus,
}
}
return (mr_ssize_t)tran_size;
return (mr_ssize_t)tf_size;
}
static mr_err_t mr_spi_device_configure_cs(mr_spi_device_t spi_device, mr_state_t state)
@@ -328,7 +337,7 @@ static mr_err_t mr_spi_device_configure_cs(mr_spi_device_t spi_device, mr_state_
pin = mr_device_find("pin");
if (pin != MR_NULL)
{
mr_device_ioctl(pin, MR_DEVICE_CTRL_SET_CONFIG, &pin_config);
return mr_device_ioctl(pin, MR_DEVICE_CTRL_SET_CONFIG, &pin_config);
}
}
#endif
@@ -339,27 +348,19 @@ static mr_err_t mr_spi_device_configure_cs(mr_spi_device_t spi_device, mr_state_
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;
/* Enable spi using the default config */
if (spi_device->config.baud_rate == 0)
{
spi_device->config = default_config;
}
mr_spi_device_configure_cs(spi_device, MR_ENABLE);
return MR_ERR_OK;
return mr_spi_device_configure_cs(spi_device, MR_ENABLE);
}
static mr_err_t mr_spi_device_close(mr_device_t device)
{
mr_spi_device_t spi_device = (mr_spi_device_t)device;
/* Disable spi */
spi_device->config.baud_rate = 0;
mr_spi_device_configure_cs(spi_device, MR_DISABLE);
/* Reset fifo */
mr_rb_reset(&spi_device->rx_fifo);
mr_rb_reset(&spi_device->tx_fifo);
return MR_ERR_OK;
return mr_spi_device_configure_cs(spi_device, MR_DISABLE);
}
static mr_err_t mr_spi_device_ioctl(mr_device_t device, int cmd, void *args)
@@ -373,6 +374,29 @@ static mr_err_t mr_spi_device_ioctl(mr_device_t device, int cmd, void *args)
if (args)
{
mr_spi_config_t config = (mr_spi_config_t)args;
mr_err_t ret = MR_ERR_OK;
if (config->host_slave != spi_device->config.host_slave)
{
if (config->host_slave == MR_SPI_HOST)
{
if (spi_device->bus != MR_NULL)
{
mr_spi_device_release_bus(spi_device);
}
} else
{
if (spi_device->bus != MR_NULL)
{
/* Slave mode monopolizes the bus */
ret = mr_spi_device_take_bus(spi_device);
if (ret != MR_ERR_OK)
{
return ret;
}
}
}
}
spi_device->config = *config;
return MR_ERR_OK;
}
@@ -403,19 +427,39 @@ static mr_err_t mr_spi_device_ioctl(mr_device_t device, int cmd, void *args)
case MR_DEVICE_CTRL_SPI_TRANSFER:
{
if(args)
if (args)
{
struct mr_spi_transfer *transfer = (struct mr_spi_transfer *)args;
mr_ssize_t tran_size = 0;
struct mr_spi_transfer *tf = (struct mr_spi_transfer *)args;
mr_ssize_t tf_size = 0;
mr_err_t ret = MR_ERR_OK;
/* Enable the chip-select of the current device */
mr_spi_device_cs_set_state(spi_device, MR_ENABLE);
/* Take the spi-bus */
ret = mr_spi_device_take_bus(spi_device);
if (ret != MR_ERR_OK)
{
return ret;
}
tran_size = mr_spi_bus_transfer(spi_device->bus, transfer->write_buffer, transfer->read_buffer, transfer->size, MR_SPI_RDWR);
if (spi_device->config.host_slave == MR_SPI_HOST)
{
/* Enable the chip-select of the current device */
mr_spi_device_cs_set_state(spi_device, MR_ENABLE);
/* Disable the chip-select of the current device */
mr_spi_device_cs_set_state(spi_device, MR_DISABLE);
return (mr_err_t)tran_size;
tf_size =
mr_spi_device_transfer(spi_device, tf->write_buffer, tf->read_buffer, tf->size, MR_SPI_RDWR);
/* Disable the chip-select of the current device */
mr_spi_device_cs_set_state(spi_device, MR_DISABLE);
} else
{
tf_size =
mr_spi_device_transfer(spi_device, tf->write_buffer, tf->read_buffer, tf->size, MR_SPI_RDWR);
}
/* Release spi-bus */
mr_spi_device_release_bus(spi_device);
return (mr_err_t)tf_size;
}
return -MR_ERR_INVALID;
}
@@ -447,24 +491,24 @@ static mr_ssize_t mr_spi_device_read(mr_device_t device, mr_off_t pos, void *buf
/* Send position */
if (pos >= 0)
{
mr_spi_bus_transfer(spi_device->bus, &pos, MR_NULL, (spi_device->config.pos_bits >> 3), MR_SPI_WR);
mr_spi_device_transfer(spi_device, &pos, MR_NULL, (spi_device->config.pos_bits >> 3), MR_SPI_WR);
}
/* Blocking read */
read_size = mr_spi_bus_transfer(spi_device->bus, MR_NULL, read_buffer, size, MR_SPI_RD);
read_size = mr_spi_device_transfer(spi_device, MR_NULL, read_buffer, size, MR_SPI_RD);
/* Disable the chip-select of the current device */
mr_spi_device_cs_set_state(spi_device, MR_DISABLE);
} else
{
if (mr_rb_get_buffer_size(&device->rx_fifo) == 0)
if (mr_rb_get_buffer_size(&spi_device->rx_fifo) == 0)
{
/* Blocking read */
read_size = mr_spi_bus_transfer(spi_device->bus, MR_NULL, read_buffer, size, MR_SPI_RD);
read_size = mr_spi_device_transfer(spi_device, MR_NULL, read_buffer, size, MR_SPI_RD);
} else
{
/* Non-blocking read */
read_size = (mr_ssize_t)mr_rb_read(&device->rx_fifo, read_buffer, size);
read_size = (mr_ssize_t)mr_rb_read(&spi_device->rx_fifo, read_buffer, size);
}
}
@@ -496,18 +540,18 @@ static mr_ssize_t mr_spi_device_write(mr_device_t device, mr_off_t pos, const vo
/* Send position */
if (pos >= 0)
{
mr_spi_bus_transfer(spi_device->bus, &pos, MR_NULL, (spi_device->config.pos_bits >> 3), MR_SPI_WR);
mr_spi_device_transfer(spi_device, &pos, MR_NULL, (spi_device->config.pos_bits >> 3), MR_SPI_WR);
}
/* Blocking write */
write_size = mr_spi_bus_transfer(spi_device->bus, write_buffer, MR_NULL, size, MR_SPI_WR);
write_size = mr_spi_device_transfer(spi_device, write_buffer, MR_NULL, size, MR_SPI_WR);
/* Disable the chip-select of the current device */
mr_spi_device_cs_set_state(spi_device, MR_DISABLE);
} else
{
/* Blocking write */
write_size = mr_spi_bus_transfer(spi_device->bus, write_buffer, MR_NULL, size, MR_SPI_WR);
write_size = mr_spi_device_transfer(spi_device, write_buffer, MR_NULL, size, MR_SPI_WR);
}
/* Release spi-bus */
@@ -535,43 +579,25 @@ mr_err_t mr_spi_device_add(mr_spi_device_t spi_device, const char *name, mr_off_
mr_spi_device_read,
mr_spi_device_write,
};
struct mr_spi_config default_config = MR_SPI_CONFIG_DEFAULT;
MR_ASSERT(spi_device != MR_NULL);
MR_ASSERT(name != MR_NULL);
MR_ASSERT(cs_number >= 0);
/* Initialize the private fields */
spi_device->config.baud_rate = 0;
spi_device->config = default_config;
mr_rb_init(&spi_device->rx_fifo, MR_NULL, 0);
mr_rb_init(&spi_device->tx_fifo, MR_NULL, 0);
spi_device->cs_number = cs_number;
spi_device->bus = MR_NULL;
/* Add the device */
return mr_device_add(&spi_device->device,
name,
Mr_Device_Type_SPI,
MR_DEVICE_OFLAG_CLOSED,
&device_ops,
MR_NULL);
}
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;
/* Enable spi using the default config */
if (spi_bus->config.baud_rate == 0)
{
spi_bus->config = default_config;
}
/* Allocate fifo using configuration size */
if (mr_rb_get_buffer_size(&device->rx_fifo) == 0)
{
mr_rb_allocate_buffer(&device->rx_fifo, MR_CFG_SPI_RX_BUFSZ);
}
mr_rb_allocate_buffer(&spi_device->rx_fifo, MR_CFG_SPI_RX_BUFSZ);
mr_rb_allocate_buffer(&spi_device->rx_fifo, MR_CFG_SPI_TX_BUFSZ);
return spi_bus->ops->configure(spi_bus, &spi_bus->config);
/* Add the device */
return mr_device_add(&spi_device->device, name, Mr_Device_Type_SPI, MR_DEVICE_OFLAG_RDWR, &device_ops, MR_NULL);
}
static mr_err_t mr_spi_bus_close(mr_device_t device)
@@ -580,6 +606,7 @@ static mr_err_t mr_spi_bus_close(mr_device_t device)
/* Disable spi */
spi_bus->config.baud_rate = 0;
mr_mutex_init(&spi_bus->lock);
return spi_bus->ops->configure(spi_bus, &spi_bus->config);
}
@@ -598,7 +625,7 @@ mr_err_t mr_spi_bus_add(mr_spi_bus_t spi_bus, const char *name, struct mr_spi_bu
{
static struct mr_device_ops device_ops =
{
mr_spi_bus_open,
MR_NULL,
mr_spi_bus_close,
MR_NULL,
MR_NULL,
@@ -612,7 +639,6 @@ mr_err_t mr_spi_bus_add(mr_spi_bus_t spi_bus, const char *name, struct mr_spi_bu
/* Initialize the private fields */
spi_bus->config.baud_rate = 0;
mr_mutex_init(&spi_bus->lock);
spi_bus->owner = MR_NULL;
/* Protect every operation of the spi-bus device */
ops->configure = ops->configure ? ops->configure : err_io_spi_configure;
@@ -640,29 +666,26 @@ void mr_spi_bus_isr(mr_spi_bus_t spi_bus, mr_uint32_t event)
{
case MR_SPI_BUS_EVENT_RX_INT:
{
mr_spi_device_t spi_device = spi_bus->owner;
mr_spi_device_t spi_device = (mr_spi_device_t)mr_mutex_get_owner(&spi_bus->lock);
/* Check if the spi device is valid */
if(spi_device != MR_NULL)
if (spi_device != MR_NULL)
{
if (spi_device->config.host_slave == MR_SPI_SLAVE)
/* Check if the chip-select is active */
if (mr_spi_device_cs_get_state(spi_device) != MR_ENABLE)
{
/* Check if the chip-select is active */
if (mr_spi_device_cs_get_state(spi_device) != MR_ENABLE)
{
return;
}
return;
}
/* Save data to the fifo */
mr_uint32_t data = spi_bus->ops->read(spi_bus);
mr_rb_write_force(&spi_bus->device.rx_fifo, &data, (spi_device->config.data_bits >> 3));
/* Save data to the fifo */
mr_uint32_t data = spi_bus->ops->read(spi_bus);
mr_rb_write_force(&spi_device->rx_fifo, &data, (spi_device->config.data_bits >> 3));
/* Call the receiving completion function */
if (spi_device->device.rx_cb != MR_NULL)
{
mr_size_t size = mr_rb_get_data_size(&spi_bus->device.rx_fifo);
spi_device->device.rx_cb(&spi_device->device, &size);
}
/* Call the receiving completion function */
if (spi_device->device.rx_cb != MR_NULL)
{
mr_size_t size = mr_rb_get_data_size(&spi_device->rx_fifo);
spi_device->device.rx_cb(&spi_device->device, &size);
}
}
break;

View File

@@ -68,8 +68,8 @@ extern "C" {
/**
* @def SPI device interrupt event
*/
#define MR_SPI_BUS_EVENT_RX_INT 0x10000000
#define MR_SPI_BUS_EVENT_MASK 0xf0000000
#define MR_SPI_BUS_EVENT_RX_INT 0x10000000
#define MR_SPI_BUS_EVENT_MASK 0xf0000000
/**
* @def SPI device default config
@@ -122,6 +122,8 @@ struct mr_spi_device
struct mr_device device;
struct mr_spi_config config;
struct mr_rb rx_fifo;
struct mr_rb tx_fifo;
mr_off_t cs_number;
mr_spi_bus_t bus;
};