1.接管中断(未测试)。
This commit is contained in:
399
device/spi/spi.c
399
device/spi/spi.c
@@ -11,16 +11,78 @@
|
||||
#include "device/spi/spi.h"
|
||||
|
||||
#if (MR_CONF_PIN == MR_CONF_ENABLE)
|
||||
|
||||
#include "device/pin/pin.h"
|
||||
|
||||
#endif
|
||||
|
||||
#if (MR_CONF_SPI == MR_CONF_ENABLE)
|
||||
|
||||
static mr_err_t mr_take_spi_bus(mr_spi_device_t spi_device)
|
||||
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.buffer)
|
||||
{
|
||||
mr_free(spi_bus->rx_fifo.buffer);
|
||||
mr_fifo_init(&spi_bus->rx_fifo, MR_NULL, 0);
|
||||
}
|
||||
|
||||
spi_bus->rx_bufsz = rx_bufsz;
|
||||
|
||||
if (spi_bus->rx_bufsz != 0)
|
||||
{
|
||||
buffer = mr_malloc(spi_bus->rx_bufsz);
|
||||
if (buffer == MR_NULL)
|
||||
{
|
||||
return -MR_ERR_NO_MEMORY;
|
||||
}
|
||||
mr_fifo_init(&spi_bus->rx_fifo, buffer, spi_bus->rx_bufsz);
|
||||
}
|
||||
|
||||
return MR_ERR_OK;
|
||||
}
|
||||
|
||||
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.buffer)
|
||||
{
|
||||
mr_free(spi_bus->tx_fifo.buffer);
|
||||
mr_fifo_init(&spi_bus->tx_fifo, MR_NULL, 0);
|
||||
}
|
||||
|
||||
spi_bus->tx_bufsz = tx_bufsz;
|
||||
|
||||
if (spi_bus->tx_bufsz != 0)
|
||||
{
|
||||
buffer = mr_malloc(spi_bus->tx_bufsz);
|
||||
if (buffer == MR_NULL)
|
||||
{
|
||||
return -MR_ERR_NO_MEMORY;
|
||||
}
|
||||
mr_fifo_init(&spi_bus->tx_fifo, buffer, spi_bus->tx_bufsz);
|
||||
}
|
||||
|
||||
return MR_ERR_OK;
|
||||
}
|
||||
|
||||
mr_inline mr_uint8_t mr_spi_bus_transfer(mr_spi_bus_t spi_bus, mr_uint8_t data)
|
||||
{
|
||||
spi_bus->ops->write(spi_bus, data);
|
||||
return spi_bus->ops->read(spi_bus);
|
||||
}
|
||||
|
||||
mr_inline mr_err_t mr_take_spi_bus(mr_spi_device_t spi_device)
|
||||
{
|
||||
mr_err_t ret = MR_ERR_OK;
|
||||
|
||||
MR_ASSERT(spi_device->bus != MR_NULL);
|
||||
/* Without attach the bus */
|
||||
if (spi_device->bus == MR_NULL)
|
||||
{
|
||||
return -MR_ERR_GENERIC;
|
||||
}
|
||||
|
||||
/* Take the mutex lock of the spi-bus */
|
||||
ret = mr_mutex_take(&spi_device->bus->lock, &spi_device->device.object);
|
||||
@@ -49,18 +111,18 @@ static mr_err_t mr_take_spi_bus(mr_spi_device_t spi_device)
|
||||
spi_device->bus->config = spi_device->config;
|
||||
spi_device->bus->owner = spi_device;
|
||||
}
|
||||
|
||||
/* Start the chip-select of the current spi-device */
|
||||
spi_device->bus->ops->cs_ctrl(spi_device->bus, spi_device->bus->owner->cs_pin, MR_ENABLE);
|
||||
|
||||
return MR_ERR_OK;
|
||||
}
|
||||
|
||||
static mr_err_t mr_release_spi_bus(mr_spi_device_t spi_device)
|
||||
mr_inline mr_err_t mr_release_spi_bus(mr_spi_device_t spi_device)
|
||||
{
|
||||
mr_err_t ret = MR_ERR_OK;
|
||||
|
||||
MR_ASSERT(spi_device->bus != MR_NULL);
|
||||
/* Without attach the bus */
|
||||
if (spi_device->bus == MR_NULL)
|
||||
{
|
||||
return -MR_ERR_GENERIC;
|
||||
}
|
||||
|
||||
/* Release the mutex lock of the spi-bus */
|
||||
ret = mr_mutex_release(&spi_device->bus->lock, &spi_device->device.object);
|
||||
@@ -69,17 +131,27 @@ static mr_err_t mr_release_spi_bus(mr_spi_device_t spi_device)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Stop the chip-select of the current spi-device */
|
||||
spi_device->bus->ops->cs_ctrl(spi_device->bus, spi_device->bus->owner->cs_pin, MR_DISABLE);
|
||||
|
||||
return MR_ERR_OK;
|
||||
}
|
||||
|
||||
static mr_err_t mr_spi_bus_open(mr_device_t device)
|
||||
{
|
||||
mr_spi_bus_t spi_bus = (mr_spi_bus_t)device;
|
||||
mr_err_t ret = MR_ERR_OK;
|
||||
struct mr_spi_config default_config = MR_SPI_CONFIG_DEFAULT;
|
||||
|
||||
/* Allocate the fifo buffer */
|
||||
ret = mr_spi_bus_rx_fifo_init(spi_bus, spi_bus->rx_bufsz);
|
||||
if (ret != MR_ERR_OK)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
ret = mr_spi_bus_tx_fifo_init(spi_bus, spi_bus->tx_bufsz);
|
||||
if (ret != MR_ERR_OK)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Setting spi-bus to default config, if the baud-rate not set */
|
||||
if (spi_bus->config.baud_rate == 0)
|
||||
{
|
||||
@@ -92,6 +164,21 @@ static mr_err_t mr_spi_bus_open(mr_device_t device)
|
||||
static mr_err_t mr_spi_bus_close(mr_device_t device)
|
||||
{
|
||||
mr_spi_bus_t spi_bus = (mr_spi_bus_t)device;
|
||||
mr_err_t ret = MR_ERR_OK;
|
||||
|
||||
/* Allocate the fifo buffer */
|
||||
ret = mr_spi_bus_rx_fifo_init(spi_bus, 0);
|
||||
if (ret != MR_ERR_OK)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
ret = mr_spi_bus_tx_fifo_init(spi_bus, 0);
|
||||
if (ret != MR_ERR_OK)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
spi_bus->rx_bufsz = MR_CONF_SPI_RX_BUFSZ;
|
||||
spi_bus->tx_bufsz = MR_CONF_SPI_TX_BUFSZ;
|
||||
|
||||
/* Setting spi-bus to close config */
|
||||
spi_bus->config.baud_rate = 0;
|
||||
@@ -99,6 +186,35 @@ static mr_err_t mr_spi_bus_close(mr_device_t device)
|
||||
return spi_bus->ops->configure(spi_bus, &spi_bus->config);
|
||||
}
|
||||
|
||||
static mr_err_t mr_spi_bus_ioctl(mr_device_t device, int cmd, void *args)
|
||||
{
|
||||
mr_spi_bus_t spi_bus = (mr_spi_bus_t)device;
|
||||
|
||||
switch (cmd & _MR_CTRL_FLAG_MASK)
|
||||
{
|
||||
case MR_CTRL_SET_RX_BUFSZ:
|
||||
{
|
||||
if (args)
|
||||
{
|
||||
return mr_spi_bus_rx_fifo_init(spi_bus, *((mr_size_t *)args));
|
||||
}
|
||||
return -MR_ERR_INVALID;
|
||||
}
|
||||
|
||||
case MR_CTRL_SET_TX_BUFSZ:
|
||||
{
|
||||
if (args)
|
||||
{
|
||||
return mr_spi_bus_tx_fifo_init(spi_bus, *((mr_size_t *)args));
|
||||
}
|
||||
return -MR_ERR_INVALID;
|
||||
}
|
||||
|
||||
default:
|
||||
return -MR_ERR_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
static mr_err_t mr_spi_device_open(mr_device_t device)
|
||||
{
|
||||
mr_spi_device_t spi_device = (mr_spi_device_t)device;
|
||||
@@ -156,14 +272,10 @@ static mr_err_t mr_spi_device_ioctl(mr_device_t device, int cmd, void *args)
|
||||
|
||||
/* Find the spi-bus */
|
||||
mr_device_t spi_bus = mr_device_find((char *)args);
|
||||
if (spi_bus == MR_NULL)
|
||||
if (spi_bus == MR_NULL || spi_bus->type != MR_DEVICE_TYPE_SPI_BUS)
|
||||
{
|
||||
return -MR_ERR_NOT_FOUND;
|
||||
}
|
||||
if (spi_bus->type != MR_DEVICE_TYPE_SPI_BUS)
|
||||
{
|
||||
return -MR_ERR_INVALID;
|
||||
}
|
||||
|
||||
/* Open the spi-bus */
|
||||
ret = mr_device_open(spi_bus, MR_OPEN_RDWR);
|
||||
@@ -190,9 +302,9 @@ static mr_err_t mr_spi_device_ioctl(mr_device_t device, int cmd, void *args)
|
||||
{
|
||||
buffer = (mr_uint8_t *)((mr_transfer_t)args)->data;
|
||||
|
||||
for (size = 0; size < ((mr_transfer_t)args)->size; size++)
|
||||
for (size = 0; size < ((mr_transfer_t)args)->size; size += sizeof(*buffer))
|
||||
{
|
||||
*buffer = spi_device->bus->ops->transfer(spi_device->bus, *buffer);
|
||||
*buffer = mr_spi_bus_transfer(spi_device->bus, *buffer);
|
||||
buffer++;
|
||||
}
|
||||
|
||||
@@ -226,16 +338,38 @@ static mr_ssize_t mr_spi_device_read(mr_device_t device, mr_off_t pos, void *buf
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Send offset */
|
||||
if (pos > 0)
|
||||
if (spi_device->config.host_slave == MR_SPI_HOST)
|
||||
{
|
||||
spi_device->bus->ops->transfer(spi_device->bus, (mr_uint8_t)pos);
|
||||
}
|
||||
/* Start the chip-select of the current spi-device */
|
||||
spi_device->bus->ops->cs_ctrl(spi_device->bus, spi_device->bus->owner->cs_pin, MR_ENABLE);
|
||||
|
||||
for (recv_size = 0; recv_size < size; recv_size += sizeof(recv_buffer))
|
||||
/* Send position */
|
||||
if (pos != 0)
|
||||
{
|
||||
mr_spi_bus_transfer(spi_device->bus, (mr_uint8_t)pos);
|
||||
}
|
||||
|
||||
/* Host blocking read */
|
||||
for (recv_size = 0; recv_size < size; recv_size += sizeof(*recv_buffer))
|
||||
{
|
||||
*recv_buffer = mr_spi_bus_transfer(spi_device->bus, 0u);
|
||||
recv_buffer++;
|
||||
}
|
||||
|
||||
/* Stop the chip-select of the current spi-device */
|
||||
spi_device->bus->ops->cs_ctrl(spi_device->bus, spi_device->bus->owner->cs_pin, MR_DISABLE);
|
||||
} else
|
||||
{
|
||||
*recv_buffer = spi_device->bus->ops->transfer(spi_device->bus, 0u);
|
||||
recv_buffer++;
|
||||
if (spi_device->bus->rx_bufsz == 0)
|
||||
{
|
||||
return -MR_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/* Slave non-blocking read */
|
||||
for (recv_size = 0; recv_size < size;)
|
||||
{
|
||||
recv_size += mr_fifo_read(&spi_device->bus->rx_fifo, recv_buffer + recv_size, size - recv_size);
|
||||
}
|
||||
}
|
||||
|
||||
/* Release spi-bus */
|
||||
@@ -249,7 +383,10 @@ static mr_ssize_t mr_spi_device_write(mr_device_t device, mr_off_t pos, const vo
|
||||
mr_spi_device_t spi_device = (mr_spi_device_t)device;
|
||||
mr_uint8_t *send_buffer = (mr_uint8_t *)buffer;
|
||||
mr_err_t ret = MR_ERR_OK;
|
||||
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;
|
||||
|
||||
/* Take spi-bus */
|
||||
ret = mr_take_spi_bus(spi_device);
|
||||
@@ -257,17 +394,87 @@ static mr_ssize_t mr_spi_device_write(mr_device_t device, mr_off_t pos, const vo
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
spi_bus = spi_device->bus;
|
||||
|
||||
/* Send offset */
|
||||
if (pos > 0)
|
||||
if (spi_bus->tx_bufsz == 0 || (spi_device->device.open_flag & MR_OPEN_NONBLOCKING) == 0)
|
||||
{
|
||||
spi_device->bus->ops->transfer(spi_device->bus, (mr_uint8_t)pos);
|
||||
}
|
||||
if (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_pin, MR_ENABLE);
|
||||
|
||||
for (send_size = 0; send_size < size; send_size += sizeof(send_buffer))
|
||||
/* Send position */
|
||||
if (pos != 0)
|
||||
{
|
||||
mr_spi_bus_transfer(spi_bus, (mr_uint8_t)pos);
|
||||
}
|
||||
}
|
||||
|
||||
/* Blocking write */
|
||||
for (send_size = 0; send_size < size; send_size += sizeof(*send_buffer))
|
||||
{
|
||||
mr_spi_bus_transfer(spi_bus, *send_buffer);
|
||||
send_buffer++;
|
||||
}
|
||||
|
||||
/* Stop the chip-select of the current device */
|
||||
if (spi_device->config.host_slave == MR_SPI_HOST)
|
||||
{
|
||||
spi_bus->ops->cs_ctrl(spi_bus, spi_device->cs_pin, MR_DISABLE);
|
||||
}
|
||||
} else
|
||||
{
|
||||
spi_device->bus->ops->transfer(spi_device->bus, *send_buffer);
|
||||
send_buffer++;
|
||||
if (spi_device->config.host_slave == MR_SPI_HOST)
|
||||
{
|
||||
/* Send position */
|
||||
if (pos != 0)
|
||||
{
|
||||
send_position = (mr_uint8_t)pos;
|
||||
for (send_size = 0; send_size < sizeof(send_position);)
|
||||
{
|
||||
send_size += mr_fifo_write(&spi_bus->tx_fifo, &send_position, sizeof(send_position));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Count the number of send */
|
||||
spi_device->tx_count += size;
|
||||
if (mr_list_is_empty(&spi_device->tx_list))
|
||||
{
|
||||
mr_list_insert_before(&spi_bus->tx_list, &spi_device->tx_list);
|
||||
}
|
||||
|
||||
/* Non-blocking write */
|
||||
for (send_size = 0; send_size < size;)
|
||||
{
|
||||
/* If this is the first write, start sending */
|
||||
if (mr_fifo_get_data_size(&spi_bus->tx_fifo) != 0)
|
||||
{
|
||||
send_size += mr_fifo_write(&spi_bus->tx_fifo, send_buffer + send_size, size - send_size);
|
||||
} else
|
||||
{
|
||||
send_size += mr_fifo_write(&spi_bus->tx_fifo, send_buffer + send_size, size - send_size);
|
||||
|
||||
/* Start the chip-select of the current device */
|
||||
if (spi_device->config.host_slave == MR_SPI_HOST)
|
||||
{
|
||||
spi_bus->ops->cs_ctrl(spi_bus, spi_device->cs_pin, MR_ENABLE);
|
||||
}
|
||||
|
||||
if ((device->open_flag & MR_OPEN_DMA) == 0)
|
||||
{
|
||||
/* Interrupt write */
|
||||
spi_bus->ops->start_tx(spi_bus);
|
||||
} else
|
||||
{
|
||||
/* DMA write */
|
||||
dma_size = mr_fifo_read(&spi_bus->tx_fifo,
|
||||
spi_bus->tx_dma,
|
||||
sizeof(spi_bus->tx_dma));
|
||||
spi_bus->ops->start_dma_tx(spi_bus, spi_bus->tx_dma, dma_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Release spi-bus */
|
||||
@@ -282,7 +489,12 @@ static mr_err_t _err_io_spi_configure(mr_spi_bus_t spi_bus, struct mr_spi_config
|
||||
return -MR_ERR_IO;
|
||||
}
|
||||
|
||||
static mr_uint8_t _err_io_spi_transfer(mr_spi_bus_t spi_bus, mr_uint8_t data)
|
||||
static void _err_io_spi_write(mr_spi_bus_t spi_bus, mr_uint8_t data)
|
||||
{
|
||||
MR_ASSERT(0);
|
||||
}
|
||||
|
||||
static mr_uint8_t _err_io_spi_read(mr_spi_bus_t spi_bus)
|
||||
{
|
||||
MR_ASSERT(0);
|
||||
return 0;
|
||||
@@ -293,13 +505,29 @@ static void _err_io_spi_cs_ctrl(mr_spi_bus_t spi_bus, mr_uint16_t cs_pin, mr_uin
|
||||
MR_ASSERT(0);
|
||||
}
|
||||
|
||||
static mr_uint8_t _err_io_spi_cs_read(mr_spi_bus_t spi_bus, mr_uint16_t cs_pin)
|
||||
{
|
||||
MR_ASSERT(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _err_io_spi_start_tx(mr_spi_bus_t spi_bus)
|
||||
{
|
||||
MR_ASSERT(0);
|
||||
}
|
||||
|
||||
static void _err_io_spi_stop_tx(mr_spi_bus_t spi_bus)
|
||||
{
|
||||
MR_ASSERT(0);
|
||||
}
|
||||
|
||||
mr_err_t mr_spi_bus_add(mr_spi_bus_t spi_bus, const char *name, void *data, struct mr_spi_bus_ops *ops)
|
||||
{
|
||||
const static struct mr_device_ops device_ops =
|
||||
{
|
||||
mr_spi_bus_open,
|
||||
mr_spi_bus_close,
|
||||
MR_NULL,
|
||||
mr_spi_bus_ioctl,
|
||||
MR_NULL,
|
||||
MR_NULL,
|
||||
};
|
||||
@@ -316,11 +544,20 @@ mr_err_t mr_spi_bus_add(mr_spi_bus_t spi_bus, const char *name, void *data, stru
|
||||
spi_bus->config.baud_rate = 0;
|
||||
spi_bus->owner = MR_NULL;
|
||||
mr_mutex_init(&spi_bus->lock);
|
||||
spi_bus->rx_bufsz = MR_CONF_SPI_RX_BUFSZ;
|
||||
mr_fifo_init(&spi_bus->rx_fifo, MR_NULL, 0);
|
||||
spi_bus->tx_bufsz = MR_CONF_SPI_TX_BUFSZ;
|
||||
mr_fifo_init(&spi_bus->tx_fifo, MR_NULL, 0);
|
||||
mr_list_init(&spi_bus->tx_list);
|
||||
|
||||
/* Set operations as protection-ops if ops is null */
|
||||
ops->configure = ops->configure ? ops->configure : _err_io_spi_configure;
|
||||
ops->transfer = ops->transfer ? ops->transfer : _err_io_spi_transfer;
|
||||
ops->write = ops->write ? ops->write : _err_io_spi_write;
|
||||
ops->read = ops->read ? ops->read : _err_io_spi_read;
|
||||
ops->cs_ctrl = ops->cs_ctrl ? ops->cs_ctrl : _err_io_spi_cs_ctrl;
|
||||
ops->cs_read = ops->cs_read ? ops->cs_read : _err_io_spi_cs_read;
|
||||
ops->start_tx = ops->start_tx ? ops->start_tx : _err_io_spi_start_tx;
|
||||
ops->stop_tx = ops->stop_tx ? ops->stop_tx : _err_io_spi_stop_tx;
|
||||
spi_bus->ops = ops;
|
||||
|
||||
/* Add to the container */
|
||||
@@ -353,6 +590,8 @@ 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_pin = cs_pin;
|
||||
mr_list_init(&spi_device->tx_list);
|
||||
spi_device->tx_count = 0;
|
||||
|
||||
#if (MR_CONF_PIN == MR_CONF_ENABLE)
|
||||
/* Configure pin */
|
||||
@@ -366,7 +605,95 @@ mr_err_t mr_spi_device_add(mr_spi_device_t spi_device, const char *name, mr_uint
|
||||
#endif /* MR_CONF_PIN */
|
||||
|
||||
/* Add to the container */
|
||||
return mr_device_add(&spi_device->device, name, MR_OPEN_RDWR);
|
||||
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_size_t dma_size = 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;
|
||||
|
||||
/* The data not belong to this device */
|
||||
if (spi_device->config.host_slave == MR_SPI_HOST ||
|
||||
spi_bus->ops->cs_read(spi_bus, spi_device->cs_pin) != spi_device->config.cs_active)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* Read data into the fifo */
|
||||
data = spi_bus->ops->read(spi_bus);
|
||||
mr_fifo_write_force(&spi_bus->rx_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);
|
||||
spi_device->device.rx_cb(&spi_device->device, &length);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case MR_SPI_BUS_EVENT_TX_INT:
|
||||
{
|
||||
/* Check if the list is not empty */
|
||||
if (!mr_list_is_empty(&spi_bus->tx_list))
|
||||
{
|
||||
spi_device = mr_container_of(spi_bus->tx_list.next, struct mr_spi_device, tx_list);
|
||||
if (spi_device->tx_count == 0)
|
||||
{
|
||||
/* Remove from the list */
|
||||
mr_list_remove(&spi_device->tx_list);
|
||||
|
||||
/* Stop the chip-select of the current device */
|
||||
if (spi_device->config.host_slave == MR_SPI_HOST)
|
||||
{
|
||||
spi_bus->ops->cs_ctrl(spi_bus, spi_device->cs_pin, MR_DISABLE);
|
||||
}
|
||||
|
||||
/* Invoke the tx-cb function */
|
||||
if (spi_device->device.tx_cb != MR_NULL)
|
||||
{
|
||||
spi_device->device.rx_cb(&spi_device->device, &spi_device->tx_count);
|
||||
}
|
||||
|
||||
/* Select next device if list not empty */
|
||||
if (!mr_list_is_empty(&spi_bus->tx_list))
|
||||
{
|
||||
spi_device = mr_container_of(spi_bus->tx_list.next, struct mr_spi_device, tx_list);
|
||||
|
||||
/* Start the chip-select of the current device */
|
||||
if (spi_device->config.host_slave == MR_SPI_HOST)
|
||||
{
|
||||
spi_bus->ops->cs_ctrl(spi_bus, spi_device->cs_pin, MR_ENABLE);
|
||||
}
|
||||
}
|
||||
} else
|
||||
{
|
||||
/* Decrement tx count */
|
||||
spi_device->tx_count--;
|
||||
|
||||
/* Write data from the fifo */
|
||||
mr_fifo_read(&spi_bus->tx_fifo, &data, sizeof(data));
|
||||
mr_spi_bus_transfer(spi_bus, data);
|
||||
}
|
||||
} else
|
||||
{
|
||||
/* Stop transmission */
|
||||
spi_bus->ops->stop_tx(spi_bus);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* MR_CONF_SPI */
|
||||
@@ -30,6 +30,15 @@
|
||||
#define MR_SPI_CS_ACTIVE_HIGH 1
|
||||
#define MR_SPI_CS_ACTIVE_NONE 2
|
||||
|
||||
#define MR_SPI_BUS_EVENT_RX_INT 0x10000000
|
||||
#define MR_SPI_BUS_EVENT_TX_INT 0x20000000
|
||||
#define MR_SPI_BUS_EVENT_RX_DMA 0x40000000
|
||||
#define MR_SPI_BUS_EVENT_TX_DMA 0x80000000
|
||||
#define _MR_SPI_BUS_EVENT_MASK 0xf0000000
|
||||
|
||||
#define _MR_SPI_BUS_STATE_IDLE 0x00
|
||||
#define _MR_SPI_BUS_STATE_RUNNING 0x10
|
||||
|
||||
/* Default config for mr_spi_config structure */
|
||||
#define MR_SPI_CONFIG_DEFAULT \
|
||||
{ \
|
||||
@@ -58,14 +67,27 @@ struct mr_spi_device
|
||||
struct mr_spi_config config;
|
||||
struct mr_spi_bus *bus;
|
||||
mr_uint16_t cs_pin;
|
||||
|
||||
struct mr_list tx_list;
|
||||
mr_size_t tx_count;
|
||||
};
|
||||
typedef struct mr_spi_device *mr_spi_device_t;
|
||||
|
||||
struct mr_spi_bus_ops
|
||||
{
|
||||
mr_err_t (*configure)(mr_spi_bus_t spi_bus, struct mr_spi_config *config);
|
||||
mr_uint8_t (*transfer)(mr_spi_bus_t spi_bus, mr_uint8_t data);
|
||||
void (*write)(mr_spi_bus_t spi_bus, mr_uint8_t data);
|
||||
mr_uint8_t (*read)(mr_spi_bus_t spi_bus);
|
||||
void (*cs_ctrl)(mr_spi_bus_t spi_bus, mr_uint16_t cs_pin, mr_uint8_t state);
|
||||
|
||||
/* Interrupt */
|
||||
mr_uint8_t (*cs_read)(mr_spi_bus_t spi_bus, mr_uint16_t cs_pin);
|
||||
void (*start_tx)(mr_spi_bus_t spi_bus);
|
||||
void (*stop_tx)(mr_spi_bus_t spi_bus);
|
||||
|
||||
/* DMA */
|
||||
void (*start_dma_tx)(mr_spi_bus_t spi_bus, mr_uint8_t *buffer, mr_size_t size);
|
||||
void (*stop_dma_tx)(mr_spi_bus_t spi_bus);
|
||||
};
|
||||
|
||||
struct mr_spi_bus
|
||||
@@ -76,11 +98,23 @@ struct mr_spi_bus
|
||||
struct mr_spi_device *owner;
|
||||
struct mr_mutex lock;
|
||||
|
||||
/* Interrupt */
|
||||
mr_size_t rx_bufsz;
|
||||
struct mr_fifo rx_fifo;
|
||||
mr_size_t tx_bufsz;
|
||||
struct mr_fifo tx_fifo;
|
||||
struct mr_list tx_list;
|
||||
|
||||
/* DMA */
|
||||
mr_uint8_t rx_dma[MR_CONF_SERIAL_RX_DMA_BUFS];
|
||||
mr_uint8_t tx_dma[MR_CONF_SERIAL_TX_DMA_BUFS];
|
||||
|
||||
const struct mr_spi_bus_ops *ops;
|
||||
};
|
||||
|
||||
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);
|
||||
void mr_spi_bus_isr(mr_spi_bus_t spi_bus, mr_uint32_t event);
|
||||
|
||||
#endif /* MR_CONF_SPI */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user