drivers: spi_nrfx_spis: Fix handling of buffer lengths
Do not limit the length of the prepared transfer to the shorter of provided TX and RX buffers if both are used. The SPIS peripheral cannot handle scattered buffers anyway, so there is no point in getting the common part of TX and RX buffers for a partial transfer, like it is done for SPI and SPIM peripherals; everything what is possible needs to be transferred in one shot. For the same reason, there is no point in calling spi_context_buffers_setup() and using the related part of the spi_context structure, hence the call is removed and buffer pointers are used directly. Also return an error if a requested transfer length exceeds the SPIS peripheral hardware limit, instead of silently limiting the transfer like it was done so far. Signed-off-by: Andrzej Głąbek <andrzej.glabek@nordicsemi.no>
This commit is contained in:
parent
7d53c61da3
commit
eafafa2816
1 changed files with 24 additions and 30 deletions
|
@ -70,8 +70,7 @@ static int configure(const struct device *dev,
|
|||
}
|
||||
|
||||
if (SPI_OP_MODE_GET(spi_cfg->operation) == SPI_OP_MODE_MASTER) {
|
||||
LOG_ERR("Master mode is not supported on %s",
|
||||
dev->name);
|
||||
LOG_ERR("Master mode is not supported on %s", dev->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -86,8 +85,7 @@ static int configure(const struct device *dev,
|
|||
}
|
||||
|
||||
if (SPI_WORD_SIZE_GET(spi_cfg->operation) != 8) {
|
||||
LOG_ERR("Word sizes other than 8 bits"
|
||||
" are not supported");
|
||||
LOG_ERR("Word sizes other than 8 bits are not supported");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -105,42 +103,36 @@ static int configure(const struct device *dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void prepare_for_transfer(const struct device *dev)
|
||||
static void prepare_for_transfer(const struct device *dev,
|
||||
const uint8_t *tx_buf, size_t tx_buf_len,
|
||||
uint8_t *rx_buf, size_t rx_buf_len)
|
||||
{
|
||||
struct spi_nrfx_data *dev_data = get_dev_data(dev);
|
||||
const struct spi_nrfx_config *dev_config = get_dev_config(dev);
|
||||
struct spi_context *ctx = &dev_data->ctx;
|
||||
int status;
|
||||
|
||||
size_t buf_len = spi_context_max_continuous_chunk(ctx);
|
||||
|
||||
if (buf_len > 0) {
|
||||
if (tx_buf_len > dev_config->max_buf_len ||
|
||||
rx_buf_len > dev_config->max_buf_len) {
|
||||
LOG_ERR("Invalid buffer sizes: Tx %d/Rx %d",
|
||||
tx_buf_len, rx_buf_len);
|
||||
status = -EINVAL;
|
||||
} else {
|
||||
nrfx_err_t result;
|
||||
|
||||
if (buf_len > dev_config->max_buf_len) {
|
||||
buf_len = dev_config->max_buf_len;
|
||||
}
|
||||
|
||||
result = nrfx_spis_buffers_set(
|
||||
&dev_config->spis,
|
||||
ctx->tx_buf,
|
||||
spi_context_tx_buf_on(ctx) ? buf_len : 0,
|
||||
ctx->rx_buf,
|
||||
spi_context_rx_buf_on(ctx) ? buf_len : 0);
|
||||
result = nrfx_spis_buffers_set(&dev_config->spis,
|
||||
tx_buf, tx_buf_len,
|
||||
rx_buf, rx_buf_len);
|
||||
if (result == NRFX_SUCCESS) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Cannot prepare for transfer. */
|
||||
status = -EIO;
|
||||
} else {
|
||||
/* Zero-length buffer provided. */
|
||||
status = 0;
|
||||
}
|
||||
|
||||
spi_context_complete(ctx, status);
|
||||
spi_context_complete(&dev_data->ctx, status);
|
||||
}
|
||||
|
||||
|
||||
static int transceive(const struct device *dev,
|
||||
const struct spi_config *spi_cfg,
|
||||
const struct spi_buf_set *tx_bufs,
|
||||
|
@ -165,9 +157,11 @@ static int transceive(const struct device *dev,
|
|||
LOG_ERR("Only buffers located in RAM are supported");
|
||||
error = -ENOTSUP;
|
||||
} else {
|
||||
spi_context_buffers_setup(&dev_data->ctx, tx_bufs, rx_bufs, 1);
|
||||
|
||||
prepare_for_transfer(dev);
|
||||
prepare_for_transfer(dev,
|
||||
tx_bufs ? tx_bufs->buffers[0].buf : NULL,
|
||||
tx_bufs ? tx_bufs->buffers[0].len : 0,
|
||||
rx_bufs ? rx_bufs->buffers[0].buf : NULL,
|
||||
rx_bufs ? rx_bufs->buffers[0].len : 0);
|
||||
|
||||
error = spi_context_wait_for_completion(&dev_data->ctx);
|
||||
}
|
||||
|
@ -232,8 +226,8 @@ static int init_spis(const struct device *dev,
|
|||
const nrfx_spis_config_t *config)
|
||||
{
|
||||
struct spi_nrfx_data *dev_data = get_dev_data(dev);
|
||||
/* This sets only default values of frequency, mode and bit order.
|
||||
* The proper ones are set in configure() when a transfer is started.
|
||||
/* This sets only default values of mode and bit order. The ones to be
|
||||
* actually used are set in configure() when a transfer is prepared.
|
||||
*/
|
||||
nrfx_err_t result = nrfx_spis_init(&get_dev_config(dev)->spis,
|
||||
config,
|
||||
|
@ -285,7 +279,7 @@ static int init_spis(const struct device *dev,
|
|||
}; \
|
||||
static const struct spi_nrfx_config spi_##idx##z_config = { \
|
||||
.spis = NRFX_SPIS_INSTANCE(idx), \
|
||||
.max_buf_len = (1 << SPIS##idx##_EASYDMA_MAXCNT_SIZE) - 1, \
|
||||
.max_buf_len = BIT_MASK(SPIS##idx##_EASYDMA_MAXCNT_SIZE), \
|
||||
}; \
|
||||
DEVICE_DT_DEFINE(SPIS(idx), \
|
||||
spi_##idx##_init, \
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue