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

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit cb024f41e2c9c5e3042f98d70329e84a7ec03ed0
Author: Jorge Guzman <[email protected]>
AuthorDate: Sun Oct 25 00:57:09 2026 -0300

    arch/risc-v/gd32vw55x: do not end an SPI DMA early
    
    The SPI driver enabled every DMA channel interrupt, and its callback
    wakes the waiter on any of them: the half transfer interrupt ended the
    exchange while the second half was still on the wire, and the single
    data mode exception, raised when a receive request waits for the bus,
    ended it at a random point.  These exceptions have no effect on the
    transfer (user manual 10.5.2).
    
    - spi: enable only the full transfer finish and access error
      interrupts.  Also indent the case labels of the SPI mode switch as
      nxstyle expects (no functional change).
    - dma: clear the exception flags but call back only along with another
      event.
    
    Tested on the GD32VW553K-START with MOSI wired to MISO (PA0-PA1):
    24-byte exchanges through spitool returned the sent data 9 times out
    of 50 before, with the end of the data missing, and 50 times out of 50
    now.
    
    Assisted-by: Claude Code:claude-opus-5-5
    Signed-off-by: Jorge Guzman <[email protected]>
---
 arch/risc-v/src/gd32vw55x/gd32vw55x_dma.c |  8 +++++--
 arch/risc-v/src/gd32vw55x/gd32vw55x_spi.c | 38 ++++++++++++++++++-------------
 2 files changed, 28 insertions(+), 18 deletions(-)

diff --git a/arch/risc-v/src/gd32vw55x/gd32vw55x_dma.c 
b/arch/risc-v/src/gd32vw55x/gd32vw55x_dma.c
index 761457e441b..34b09e63d9a 100644
--- a/arch/risc-v/src/gd32vw55x/gd32vw55x_dma.c
+++ b/arch/risc-v/src/gd32vw55x/gd32vw55x_dma.c
@@ -436,9 +436,13 @@ static int gd32_dma_interrupt(int irq, void *context, void 
*arg)
     {
       gd32_dma_interrupt_flag_clear(dmachan->chan_num, status);
 
-      /* Invoke the DMA callback */
+      /* Invoke the DMA callback.  The single data mode and FIFO exceptions
+       * have no effect on the transfer (user manual 10.5.2): they are only
+       * reported along with another event.
+       */
 
-      if (dmachan->callback != NULL)
+      if (dmachan->callback != NULL &&
+          (status & ~(DMA_INTF_SDEIF | DMA_INTF_FEEIF)) != 0)
         {
           dmachan->callback(dmachan, (uint16_t)status, dmachan->arg);
         }
diff --git a/arch/risc-v/src/gd32vw55x/gd32vw55x_spi.c 
b/arch/risc-v/src/gd32vw55x/gd32vw55x_spi.c
index c6080d9dce5..1f4723c1094 100644
--- a/arch/risc-v/src/gd32vw55x/gd32vw55x_spi.c
+++ b/arch/risc-v/src/gd32vw55x/gd32vw55x_spi.c
@@ -98,9 +98,15 @@
 
 #ifdef CONFIG_GD32VW55X_SPI_DMA
 
-/* The DMA interrupts that are enabled while an SPI DMA is in progress */
+/* The DMA interrupts that are enabled while an SPI DMA is in progress:
+ * the end of the transfer and the access error.  The callback wakes the
+ * waiter on any interrupt, so the half transfer interrupt must stay off,
+ * or the exchange would end while the second half is still on the wire,
+ * and so must the single data mode exception, which a receive request
+ * raises when it waits for the bus and which does not stop the transfer.
+ */
 
-#  define SPI_DMA_INTEN         (DMA_INT_MASK)
+#  define SPI_DMA_INTEN         (DMA_CHXCTL_FTFIE | DMA_CHXCTL_TAEIE)
 
 /* SPI DMA priority */
 
@@ -627,24 +633,24 @@ static void spi_setmode(struct spi_dev_s *dev, enum 
spi_mode_e mode)
     {
       switch (mode)
         {
-        case SPIDEV_MODE0: /* CKPL=0, CKPH=0 */
-          setbits = 0;
-          break;
+          case SPIDEV_MODE0: /* CKPL=0, CKPH=0 */
+            setbits = 0;
+            break;
 
-        case SPIDEV_MODE1: /* CKPL=0, CKPH=1 */
-          setbits = SPI_CTL0_CKPH;
-          break;
+          case SPIDEV_MODE1: /* CKPL=0, CKPH=1 */
+            setbits = SPI_CTL0_CKPH;
+            break;
 
-        case SPIDEV_MODE2: /* CKPL=1, CKPH=0 */
-          setbits = SPI_CTL0_CKPL;
-          break;
+          case SPIDEV_MODE2: /* CKPL=1, CKPH=0 */
+            setbits = SPI_CTL0_CKPL;
+            break;
 
-        case SPIDEV_MODE3: /* CKPL=1, CKPH=1 */
-          setbits = SPI_CTL0_CKPH | SPI_CTL0_CKPL;
-          break;
+          case SPIDEV_MODE3: /* CKPL=1, CKPH=1 */
+            setbits = SPI_CTL0_CKPH | SPI_CTL0_CKPL;
+            break;
 
-        default:
-          return;
+          default:
+            return;
         }
 
       /* The clock configuration can only be changed while the SPI is

Reply via email to