Bug in SPI in DMA mode code (3.5.285)

Page 361 of the RSL10_hardware_reference manual says:

CAUTION: When the DMA interface is used to control transfers that use
an interface or peripheral, all accesses to that interface or
peripheral’s data registers using the peripheral bus clears the DMA
request signals. If a DMA request signal is cleared due to an ARM
Cortex-M3 processor access, the underlying DMA transfer becomes corrupted.

and yet the code does exactly that. The symptom was that the SPI in DMA mode was working correctly a few thousand times and then is was stopping after the first 16 bytes were sent. I’ve changed the order of the instructions placing the dma->Start last and that cured the problem.

In SPI_RSLxx.c @ line 1541

     dma->ConfigureAddr( spi->info->default_cfg.tx_dma_ch, &buffTCfg );

     /* Start the tx dma channel */
-    dma->Start( spi->info->default_cfg.tx_dma_ch );
-
     /* !!!WORKAROUND!!! set the RW transfer before setting the dma control to properly send first byte */
     spi->reg->CTRL0 &= ~SPI0_CTRL0_SPI0_CONTROLLER_Pos;
-    spi->reg->CTRL1 |= ( SPI0_START | transferType );
+    // spi->reg->CTRL1 |= (SPI0_START | transferType);
     spi->reg->CTRL0 |= SPI0_CONTROLLER_DMA;
+    dma->Start( spi->info->default_cfg.tx_dma_ch );
   }
   else
   {

another issue is when you configure the SPI as “master ss unused” (mode 0x10). Then the code will reconfigure your ssel pin anyways.

In SPI_RSLxx.c @ line 1005 I’ve changed:

         /* Prepare offset for configuration */
         uint32_t      offset = 0;
+        bool          ssel_config = true;

         /* Check if spi1 was selected */
         if( spi->reg == SPI1 )
         {
+#if( RTE_SPI1_MODE_DEFAULT == 0x10 )
+          ssel_config = false;
+#endif
           /* Change offset to spi1 */
           offset = SPI1_OFFSET;
        }
         else
         {
+#if( RTE_SPI0_MODE_DEFAULT == 0x10 )
+          ssel_config = false;
+#endif
           /* Reset SPI0 register */
           gpio->ResetAltFuncRegister( GPIO_FUNC_REG_SPI0 );
         }
         gpioLocCfg.io_mode = GPIO_MODE_SPI0_CLK_OUT + offset;
         gpio->ConfigurePad( spi->info->default_cfg.sclk_pin, &gpioLocCfg );

-        /* Configure ssel pin */
-        gpioLocCfg.io_mode = GPIO_MODE_SPI0_CS_OUT + offset;
-        gpio->ConfigurePad( spi->info->default_cfg.ssel_pin, &gpioLocCfg );
+        if( ssel_config )
+        {
+          /* Configure ssel pin */
+          gpioLocCfg.io_mode = GPIO_MODE_SPI0_CS_OUT + offset;
+          gpio->ConfigurePad( spi->info->default_cfg.ssel_pin, &gpioLocCfg );
+        }

         /* Configure miso pin */
         gpioLocCfg.io_mode = GPIO_MODE_SPI0_SERI_IN + offset;
             case ARM_SPI_SS_MASTER_UNUSED:
             {
-              /* Unconfigure SSEL Pin */
-              gpioLocCfg.io_mode = GPIO_MODE_DISABLED;
-              gpio->ConfigurePad( spi->info->default_cfg.ssel_pin,
-                  &gpioLocCfg );
+              if( ssel_config )
+              {
+                /* Unconfigure SSEL Pin */
+                gpioLocCfg.io_mode = GPIO_MODE_DISABLED;
+                gpio->ConfigurePad( spi->info->default_cfg.ssel_pin,
+                    &gpioLocCfg );
+              }
               mode |= ARM_SPI_SS_MASTER_UNUSED;
               break;
             }
2 Likes

Thank you for reporting this issue and sharing the fixes with the user community!

Your suggested fixes are welcomed and we will add this to our items to be addressed in future releases.

2 Likes