This is an automated email from the ASF dual-hosted git repository.
xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new aeab6fbf989 spi: let a sequence keep the chip select asserted
aeab6fbf989 is described below
commit aeab6fbf9890fc1f17253d086760645a434d668a
Author: p-szafonimateusz <[email protected]>
AuthorDate: Tue Jul 14 15:12:40 2026 +0200
spi: let a sequence keep the chip select asserted
spi_transfer() always de-selects the device at the end of a sequence, so
a caller cannot express "keep CS asserted for the next sequence". A
protocol backend needs that: virtio-spi carries a cs_change flag whose
false value means the next request continues on the same chip select.
Add spi_sequence_s.keepcs. When it is set the trailing SPI_SELECT() is
skipped; an aborted sequence (ret < 0) still de-selects, so CS is never
left asserted after an error. Honor HWFEAT_FORCE_CS_ACTIVE/INACTIVE_AFTER_
TRANSFER in the per-transfer de-select decision as well.
Signed-off-by: p-szafonimateusz <[email protected]>
---
drivers/spi/spi_transfer.c | 27 +++++++++++++++++++++++++--
include/nuttx/spi/spi_transfer.h | 1 +
2 files changed, 26 insertions(+), 2 deletions(-)
diff --git a/drivers/spi/spi_transfer.c b/drivers/spi/spi_transfer.c
index cb38c37abee..c26e3d5f5a6 100644
--- a/drivers/spi/spi_transfer.c
+++ b/drivers/spi/spi_transfer.c
@@ -95,6 +95,8 @@ int spi_transfer(FAR struct spi_dev_s *spi, FAR struct
spi_sequence_s *seq)
for (i = 0, trans = seq->trans; i < (int)seq->ntrans; i++, trans++)
{
+ bool deselect = trans->deselect;
+
/* Establish the fixed SPI attributes for unique to this transaction */
#ifdef CONFIG_SPI_HWFEATURES
@@ -104,6 +106,19 @@ int spi_transfer(FAR struct spi_dev_s *spi, FAR struct
spi_sequence_s *seq)
spierr("ERROR: SPI_HWFEATURES failed: %d\n", ret);
break;
}
+
+# ifdef CONFIG_SPI_CS_CONTROL
+ /* The CS forcing features override the per-transfer deselect */
+
+ if ((trans->hwfeat & HWFEAT_FORCE_CS_INACTIVE_AFTER_TRANSFER) != 0)
+ {
+ deselect = true;
+ }
+ else if ((trans->hwfeat & HWFEAT_FORCE_CS_ACTIVE_AFTER_TRANSFER) != 0)
+ {
+ deselect = false;
+ }
+# endif
#endif
#ifdef CONFIG_SPI_CMDDATA
@@ -125,7 +140,7 @@ int spi_transfer(FAR struct spi_dev_s *spi, FAR struct
spi_sequence_s *seq)
/* Possibly de-select the SPI device after the transfer */
- if (trans->deselect)
+ if (deselect)
{
SPI_SELECT(spi, seq->dev, false);
}
@@ -138,7 +153,15 @@ int spi_transfer(FAR struct spi_dev_s *spi, FAR struct
spi_sequence_s *seq)
}
}
- SPI_SELECT(spi, seq->dev, false);
+ /* De-select unless the sequence keeps CS asserted for a follow-up
+ * sequence; an aborted sequence always de-selects.
+ */
+
+ if (!seq->keepcs || ret < 0)
+ {
+ SPI_SELECT(spi, seq->dev, false);
+ }
+
SPI_LOCK(spi, false);
return ret;
}
diff --git a/include/nuttx/spi/spi_transfer.h b/include/nuttx/spi/spi_transfer.h
index 8ec086ca45a..e0fd87e14ee 100644
--- a/include/nuttx/spi/spi_transfer.h
+++ b/include/nuttx/spi/spi_transfer.h
@@ -101,6 +101,7 @@ struct spi_sequence_s
uint8_t mode; /* See enum spi_mode_e */
uint8_t nbits; /* Number of bits */
uint8_t ntrans; /* Number of transactions */
+ uint8_t keepcs; /* Keep CS asserted after the sequence */
uint32_t frequency; /* SPI frequency (Hz) */
#ifdef CONFIG_SPI_DELAY_CONTROL
uint32_t a; /* Arguments to setdelay() */