cancel
Showing results for 
Search instead for 
Did you mean: 

SPI DMA: Wrong transmission values, but only for large messages

Corono
Associate III

Hi

I'm trying to implement SPI over DMA for a STM32F091RC MCU. The slave is the ADS124S08 from TI (https://www.ti.com/product/ADS124S08)

The SPI initialization:

/* SPI1 parameter configuration*/
  hspi1.Instance                = SPI1;
  hspi1.Init.Mode               = SPI_MODE_MASTER;
  hspi1.Init.Direction          = SPI_DIRECTION_2LINES;
  hspi1.Init.DataSize           = SPI_DATASIZE_8BIT;
  hspi1.Init.CLKPolarity        = SPI_POLARITY_LOW;
  hspi1.Init.CLKPhase           = SPI_PHASE_1EDGE;
  hspi1.Init.NSS                = SPI_NSS_SOFT;
  hspi1.Init.BaudRatePrescaler  = SPI_BAUDRATEPRESCALER_4;
  hspi1.Init.FirstBit           = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode             = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation     = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.CRCPolynomial      = 7;
  hspi1.Init.CRCLength          = SPI_CRC_LENGTH_DATASIZE;
  hspi1.Init.NSSPMode           = SPI_NSS_PULSE_DISABLE;
  //Works only for temperature sensor, external inputs need configuration first
  hspi1.Init.CLKPhase           = SPI_PHASE_2EDGE;
 
  if (HAL_SPI_Init(&hspi1)     != HAL_OK)
  {
	LOG_P(LOG_ERROR, "Error in SPI1 initialization, error code %u", hspi1.ErrorCode);
    Error_Handler();
  }

The DMA initialization:

/* SPI1 DMA Init */
    /* SPI1_TX Init */
    hdma_spi1_tx.Instance = DMA1_Channel3;
    hdma_spi1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_spi1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_spi1_tx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_spi1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_spi1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_spi1_tx.Init.Mode = DMA_NORMAL;
    hdma_spi1_tx.Init.Priority = DMA_PRIORITY_MEDIUM;
    if (HAL_DMA_Init(&hdma_spi1_tx) != HAL_OK)
    {
      Error_Handler();
    }

The MOSI sending part:

static void set_ADS124S08_Registers_DMA(uint8_t cs_number,
                                     uint8_t reg02, uint8_t reg03, uint8_t reg04,
                                     uint8_t reg05, uint8_t reg06, uint8_t reg07,
                                     uint8_t reg08, uint8_t reg10, uint8_t reg11)
{
	  uint8_t spiDataSend[30];
 
	  // -----------------------------------------------------
	  set_CS_on_74HC595(cs_number);
	  // -----------------------------------------------------
 
	  // -----------------------------------------------------
	  // set AIN5+4-   ---------------------------------------
	  spiDataSend[0] = 0x42;
	  spiDataSend[1] = 0x00;
	  spiDataSend[2] = reg02;
	  // -----------------------------------------------------
	  // set Gain PGA Enabled; Gain Selection ----------------
	  // -----------------------------------------------------
	  spiDataSend[3] = 0x43;
	  spiDataSend[4] = 0x00;
	  spiDataSend[5] = reg03;
	  // -----------------------------------------------------
	  // set Data rate selection -----------------------------
	  // -----------------------------------------------------
	  spiDataSend[6] = 0x44;
	  spiDataSend[7] = 0x00;
	  spiDataSend[8] = reg04;
	  // -----------------------------------------------------
	  // set REF: Internal voltage reference enabled ---------
	  // -----------------------------------------------------
	  spiDataSend[9] = 0x45;
	  spiDataSend[10] = 0x00;
	  spiDataSend[11] = reg05;
	  // -----------------------------------------------------
	  // set IMAG: IDAC mag.sel. = 250 uA --------------------
	  // -----------------------------------------------------
	  spiDataSend[12] = 0x46;
	  spiDataSend[13] = 0x00;
	  spiDataSend[14] = reg06;
	  // -----------------------------------------------------
	  // set VBIAS to Default Value --------------------------
	  // -----------------------------------------------------
	  spiDataSend[15] = 0x48;
	  spiDataSend[16] = 0x00;
	  spiDataSend[17] = reg08;
	  // -----------------------------------------------------
	  // set GPIODAT to Default Value ------------------------
	  // -----------------------------------------------------
	  spiDataSend[18] = 0x50;
	  spiDataSend[19] = 0x00;
	  spiDataSend[20] = reg10;
	  // -------------------------
	  //----------------------------
	  // set GPIOCON to Default Value ------------------------
	  // -----------------------------------------------------
	  spiDataSend[21] = 0x51;
	  spiDataSend[22] = 0x00;
	  spiDataSend[23] = reg11;
	  // -----------------------------------------------------
	  // set 1 MUX AIN 5 = 0101 ------------------------------
	  // -----------------------------------------------------
	  spiDataSend[24] = 0x47;
	  spiDataSend[25] = 0x00;
	  spiDataSend[26] = reg07;
	  // -----------------------------------------------------
	  // START (only one byte to transmit) -------------------
	  // -----------------------------------------------------
	  spiDataSend[27] = 0x08;
	  spiDataSend[28] = 0x00;
	  spiDataSend[29] = 0x00;
	  // -----------------------------------------------------
	  if (HAL_SPI_Transmit_DMA(&hspi1,spiDataSend,30) != HAL_OK)
	  {
		LOG_P(LOG_ERROR, "Error in SPI1 transmission, error code %u", hspi1.ErrorCode);
	    Error_Handler();
	  }
	  // -----------------------------------------------------
 
	  // -----------------------------------------------------
 
 
	  // -----------------------------------------------------
}

When I have a look at the transmission:

0693W000001t2eqQAA.png

All bytes are right until the 46 00 00. The next should be 48, but is 00. From then, all bytes are wrong. The strange thing: If I set a breakpoint befor the SPI_Transmit command and make one step forward, it works:

0693W000001t2huQAA.png

My idea was that it has something to do with a full buffer. So I reduced the number of bytes. The strange thing: Only sendig 16 bytes gives:

0693W000001t2ixQAA.png

The B8 is the first wrong byte. But increasing now to 17 bytes:

0693W000001t2jvQAA.pngAt this point, my buffer theory makes no sense anymore because this is a correct transmission.

Any idea why this happens and how I can solve this?

Thanks.

Corono

1 ACCEPTED SOLUTION

Accepted Solutions
TDK
Guru

spiDataSend is a local array. It's on the stack. Once the function exits, that space is reallocated by the next function.

To send data through DMA, the buffer you're sending need to remain valid until the transmission is done. Use a global buffer instead. Or a local static buffer.

If you feel a post has answered your question, please click "Accept as Solution".

View solution in original post

2 REPLIES 2
TDK
Guru

spiDataSend is a local array. It's on the stack. Once the function exits, that space is reallocated by the next function.

To send data through DMA, the buffer you're sending need to remain valid until the transmission is done. Use a global buffer instead. Or a local static buffer.

If you feel a post has answered your question, please click "Accept as Solution".
Corono
Associate III

Hi

Thanks for your answer. Make sense.

Problem solved.