2020-07-16 07:24 AM
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:
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:
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:
The B8 is the first wrong byte. But increasing now to 17 bytes:
At 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
Solved! Go to Solution.
2020-07-16 12:20 PM
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.
2020-07-16 12:20 PM
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.
2020-07-17 12:23 AM
Hi
Thanks for your answer. Make sense.
Problem solved.