This is an automated email from the ASF dual-hosted git repository.

simbit18 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 22bc630d9f9 drivers/kinetis/spi: Fix Kinetis DSPI transfers in 
non-FIFO mode.
22bc630d9f9 is described below

commit 22bc630d9f94d0eb4a38a0adc0910a70570f7500
Author: trns1997 <[email protected]>
AuthorDate: Thu Oct 2 18:18:00 2025 +0200

    drivers/kinetis/spi: Fix Kinetis DSPI transfers in non-FIFO mode.
    
    Fix a transfer issue in the Kinetis DSPI driver when operating
    with transmit and receive FIFOs disabled (`MCR[DIS_TXF]=1`,
    `MCR[DIS_RXF]=1`). In this mode, the DSPI module behaves as a
    simple double-buffered SPI interface without TX staging.
    
    When FIFOs are disabled, `PUSHR` acts as a single 32-bit
    command/data register. Partial (16-bit) writes to its upper or
    lower halves can result in incomplete or corrupted transfers.
    This patch ensures the full 32-bit packet is prepared and
    written in a single operation.
    
    * Resolves broken SPI transactions with LAN9252 (EasyCAT).
    * Improves reliability in non-FIFO DSPI configurations.
    * No impact on DMA or FIFO-enabled modes.
    
    Signed-off-by: trns1997 <[email protected]>
---
 arch/arm/src/kinetis/kinetis_spi.c                 | 65 ++++++++++++++++------
 boards/arm/kinetis/freedom-k64f/include/board.h    | 13 +++++
 boards/arm/kinetis/freedom-k64f/src/freedom-k64f.h |  3 +
 boards/arm/kinetis/freedom-k64f/src/k64_boot.c     |  2 +-
 boards/arm/kinetis/freedom-k64f/src/k64_bringup.c  | 16 ++++++
 boards/arm/kinetis/freedom-k64f/src/k64_spi.c      |  4 +-
 6 files changed, 84 insertions(+), 19 deletions(-)

diff --git a/arch/arm/src/kinetis/kinetis_spi.c 
b/arch/arm/src/kinetis/kinetis_spi.c
index b7c603b5125..98ddc9766f8 100644
--- a/arch/arm/src/kinetis/kinetis_spi.c
+++ b/arch/arm/src/kinetis/kinetis_spi.c
@@ -134,7 +134,7 @@ static inline void     spi_putreg8(struct kinetis_spidev_s 
*priv,
                                    uint8_t offset, uint8_t value);
 static inline uint16_t spi_readword(struct kinetis_spidev_s *priv);
 static inline void     spi_writeword(struct kinetis_spidev_s *priv,
-                                     uint16_t word);
+                                     uint16_t word, bool first_word);
 
 static inline void     spi_run(struct kinetis_spidev_s *priv,
                                bool enable);
@@ -559,11 +559,14 @@ static inline void spi_write_control(struct 
kinetis_spidev_s *priv,
  * Name: spi_writeword
  *
  * Description:
- *   Write one 16 bit word to SPI TX FIFO
+ *   Write one word to SPI TX FIFO or single-entry buffer.
+ *   In non-FIFO mode, performs 32-bit write including control bits.
+ *   In FIFO-enabled mode, writes only the data (control handled separately).
  *
  * Input Parameters:
  *   priv - Device-specific state data
  *   word - word to send
+ *   first_word - Flag to set control in case of FIFO disabled
  *
  * Returned Value:
  *   None
@@ -571,15 +574,36 @@ static inline void spi_write_control(struct 
kinetis_spidev_s *priv,
  ****************************************************************************/
 
 static inline void spi_writeword(struct kinetis_spidev_s *priv,
-                                 uint16_t word)
+                                 uint16_t word, bool first_word)
 {
+  uint32_t mcr = spi_getreg(priv, KINETIS_SPI_MCR_OFFSET);
+  uint32_t pushr_val;
+
   /* Wait until there is space in the fifo */
 
   spi_wait_status(priv, SPI_SR_TFFF);
 
-  /* Write the data to transmitted to the SPI Data Register */
+  if (mcr & SPI_MCR_DIS_TXF)
+    {
+      /* FIFO disabled: 32-bit write including control + data */
+
+      pushr_val = SPI_PUSHR_TXDATA(word);
+
+      if (first_word)
+        {
+          /* Set Control word */
+
+          pushr_val |= SPI_PUSHR_CTAS_CTAR0 | SPI_PUSHR_CTCNT;
+        }
+
+      spi_putreg(priv, KINETIS_SPI_PUSHR_OFFSET, pushr_val);
+    }
+  else
+    {
+      /* FIFO enabled: write only data; control handled separately */
 
-  spi_putreg16(priv, KINETIS_SPI_PUSHR_OFFSET, SPI_PUSHR_TXDATA(word));
+      spi_putreg16(priv, KINETIS_SPI_PUSHR_OFFSET, SPI_PUSHR_TXDATA(word));
+    }
 }
 
 /****************************************************************************
@@ -964,16 +988,27 @@ static uint16_t spi_send_data(struct kinetis_spidev_s 
*priv, uint16_t wd,
                               bool last)
 {
   uint16_t ret;
+  uint32_t mcr = spi_getreg(priv, KINETIS_SPI_MCR_OFFSET);
+  bool first_word = false;
 
-  /* On first write set control word and start transfer */
+  /* Start module and write control if FIFO enabled on first transfer */
 
-  if (0 == (spi_getreg(priv, KINETIS_SPI_SR_OFFSET) & SPI_SR_TXRXS))
+  if ((spi_getreg(priv, KINETIS_SPI_SR_OFFSET) & SPI_SR_TXRXS) == 0)
     {
       spi_run(priv, true);
-      spi_write_control(priv, SPI_PUSHR_CTAS_CTAR0 | SPI_PUSHR_CTCNT);
+      first_word = true;
+
+      if ((mcr & SPI_MCR_DIS_TXF) == 0)
+        {
+          /* FIFO enabled: safe to write control separately */
+
+          spi_write_control(priv, SPI_PUSHR_CTAS_CTAR0 | SPI_PUSHR_CTCNT);
+        }
+
+      /* Non-FIFO mode: first_word flag used in spi_writeword() */
     }
 
-  spi_writeword(priv, wd);
+  spi_writeword(priv, wd, first_word);
   ret = spi_readword(priv);
 
   if (!last)
@@ -1037,15 +1072,14 @@ static uint32_t spi_send(struct spi_dev_s *dev, 
uint32_t wd)
  *
  ****************************************************************************/
 
-#if !defined(CONFIG_STM32_SPI_DMA) || defined(CONFIG_STM32_SPI_DMATHRESHOLD)
-#  if !defined(CONFIG_KINETIS_SPI_DMA)
+#if !defined(CONFIG_KINETIS_SPI_DMA)
 static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer,
                          void *rxbuffer, size_t nwords)
-#  else
+#else
 static void spi_exchange_nodma(struct spi_dev_s *dev,
                                const void *txbuffer,
                                void *rxbuffer, size_t nwords)
-#  endif
+#endif
 {
   struct kinetis_spidev_s *priv = (struct kinetis_spidev_s *)dev;
   uint8_t        *brxptr = (uint8_t *)rxbuffer;
@@ -1117,7 +1151,6 @@ static void spi_exchange_nodma(struct spi_dev_s *dev,
         }
     }
 }
-#endif /* !defined(CONFIG_STM32_SPI_DMA) || 
defined(CONFIG_STM32_SPI_DMATHRESHOLD) */
 
 /****************************************************************************
  * Name: spi_exchange (with DMA capability)
@@ -1620,13 +1653,13 @@ struct spi_dev_s *kinetis_spibus_initialize(int port)
    *   Peripheral Chip Select Strobe    - Peripheral Chip Select[5] signal
    *   Receive FIFO Overflow Overwrite  - Ignore incoming
    *   Chip Select x Inactive State     - High
-   *   Doze                             -  Disabled
+   *   Doze                             - Disabled
    *   Module Disable                   - Enables the module clocks.
    *   Disable Transmit FIFO            - yes
    *   Disable Receive FIFO             - yes
    *   Clear TX FIFO                    - No
    *   Clear RX FIFO                    - No
-   *   Sample Point                     -  0 clocks between edge and sample
+   *   Sample Point                     - 0 clocks between edge and sample
    *
    */
 
diff --git a/boards/arm/kinetis/freedom-k64f/include/board.h 
b/boards/arm/kinetis/freedom-k64f/include/board.h
index 84b33c3261a..6718de6ef26 100644
--- a/boards/arm/kinetis/freedom-k64f/include/board.h
+++ b/boards/arm/kinetis/freedom-k64f/include/board.h
@@ -297,4 +297,17 @@
 #define PIN_I2C0_SCL      PIN_I2C0_SCL_4
 #define PIN_I2C0_SDA      PIN_I2C0_SDA_4
 
+/* SPI Bus 0
+ *
+ *   Arduino   Pin              FRDM-K64F J1 Connector
+ *   ------------------------ -----------------------
+ *   SPI CLK,  Arduino D13      Pin 94, PTD1, SPI0_SCK
+ *   SPI MISO, Arduino D12      Pin 95, PTD3, SPI0_SOUT
+ *   SPI MOSI, Arduino D11      Pin 96, PTD2, SPI0_SIN
+ */
+
+#define PIN_SPI0_SCK    PIN_SPI0_SCK_3
+#define PIN_SPI0_SIN    PIN_SPI0_SIN_3
+#define PIN_SPI0_OUT    PIN_SPI0_SOUT_3
+
 #endif /* __BOARDS_ARM_FREEDOM_K64F_INCLUDE_BOARD_H */
diff --git a/boards/arm/kinetis/freedom-k64f/src/freedom-k64f.h 
b/boards/arm/kinetis/freedom-k64f/src/freedom-k64f.h
index ae0450dad58..d6c57b9a3ed 100644
--- a/boards/arm/kinetis/freedom-k64f/src/freedom-k64f.h
+++ b/boards/arm/kinetis/freedom-k64f/src/freedom-k64f.h
@@ -213,6 +213,9 @@
 #define GPIO_LED_G         (GPIO_LOWDRIVE | GPIO_OUTPUT_ONE | PIN_PORTE | 
PIN26)
 #define GPIO_LED_B         (GPIO_LOWDRIVE | GPIO_OUTPUT_ONE | PIN_PORTB | 
PIN21)
 
+/* SPI CS,   Arduino D10      Pin 93, PTD0, PIN_SPI0_PCS0_2 */
+#define GPIO_SPI0_CS       (GPIO_LOWDRIVE | GPIO_OUTPUT_ONE | PIN_PORTC | PIN4)
+
 /****************************************************************************
  * Public Data
  ****************************************************************************/
diff --git a/boards/arm/kinetis/freedom-k64f/src/k64_boot.c 
b/boards/arm/kinetis/freedom-k64f/src/k64_boot.c
index afd5a8e9ee4..57f95848d85 100644
--- a/boards/arm/kinetis/freedom-k64f/src/k64_boot.c
+++ b/boards/arm/kinetis/freedom-k64f/src/k64_boot.c
@@ -51,7 +51,7 @@
 
 void kinetis_boardinitialize(void)
 {
-#if defined(CONFIG_KINETIS_SPI1) || defined(CONFIG_KINETIS_SPI2)
+#if defined(CONFIG_KINETIS_SPI0) || defined(CONFIG_KINETIS_SPI1) || 
defined(CONFIG_KINETIS_SPI2)
   /* Configure SPI chip selects if 1) SPI is not disabled, and 2)
    * the weak function k64_spidev_initialize() has been brought into the
    * link.
diff --git a/boards/arm/kinetis/freedom-k64f/src/k64_bringup.c 
b/boards/arm/kinetis/freedom-k64f/src/k64_bringup.c
index d9d8b2992b0..9b050d49938 100644
--- a/boards/arm/kinetis/freedom-k64f/src/k64_bringup.c
+++ b/boards/arm/kinetis/freedom-k64f/src/k64_bringup.c
@@ -48,6 +48,9 @@
 #  define LED_DRIVER_PATH "/dev/userleds"
 #endif
 
+#include <nuttx/spi/spi_transfer.h>
+
+#include "kinetis_spi.h"
 #include "freedom-k64f.h"
 
 #if defined(CONFIG_BOARDCTL) || defined(CONFIG_BOARD_LATE_INITIALIZE)
@@ -102,6 +105,19 @@ int k64_bringup(void)
   k64_i2cdev_initialize();
 #endif
 
+#ifdef CONFIG_KINETIS_SPI0
+  struct spi_dev_s *spi0;
+  spi0 = kinetis_spibus_initialize(0);
+
+  if (!spi0)
+    {
+      syslog(LOG_ERR, "ERROR:FAILED to initialize SPI port 0\n");
+      return -ENODEV;
+    }
+
+  spi_register(spi0, 0);
+#endif
+
 #ifdef HAVE_MMCSD
   /* Initialize the SDHC driver */
 
diff --git a/boards/arm/kinetis/freedom-k64f/src/k64_spi.c 
b/boards/arm/kinetis/freedom-k64f/src/k64_spi.c
index b25d3033e94..6e59bc40b2b 100644
--- a/boards/arm/kinetis/freedom-k64f/src/k64_spi.c
+++ b/boards/arm/kinetis/freedom-k64f/src/k64_spi.c
@@ -57,7 +57,7 @@
 
 void weak_function k64_spidev_initialize(void)
 {
-# warning "Missing logic"
+  kinetis_pinconfig(GPIO_SPI0_CS);
 }
 
 /****************************************************************************
@@ -98,7 +98,7 @@ void kinetis_spi0select(struct spi_dev_s *dev, uint32_t devid,
 {
   spiinfo("devid: %d CS: %s\n", (int)devid,
           selected ? "assert" : "de-assert");
-# warning "Missing logic"
+  kinetis_gpiowrite(GPIO_SPI0_CS, !selected);
 }
 
 uint8_t kinetis_spi0status(struct spi_dev_s *dev, uint32_t devid)

Reply via email to