Skip to main content
Corono
Associate II
July 16, 2020
Solved

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

  • July 16, 2020
  • 2 replies
  • 1122 views

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

This topic has been closed for replies.
Best answer by TDK

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.

2 replies

TDK
TDKBest answer
Super User
July 16, 2020

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
CoronoAuthor
Associate II
July 17, 2020

Hi

Thanks for your answer. Make sense.

Problem solved.