cancel
Showing results for 
Search instead for 
Did you mean: 

SPI DMA multimaster setup, buffert size issues

MBohm
Associate II

Hello

Im working on a multimaster setup, but having alot of problems setting it up.

the processor in use is stm32f765zg

This is my pin setup(msp):

SPI2_SCK_GPIO_CLK_ENABLE();
    SPI2_MISO_GPIO_CLK_ENABLE();
    SPI2_MOSI_GPIO_CLK_ENABLE();
    SPI2_CS_GPIO_CLK_ENABLE();
    SPI2_MASTR_TRIG_GPIO_CLK_ENABLE();
 
    /* Enable SPI2 clock */
    SPI2_CLK_ENABLE();
    /* Enable DMA clock */
    DMA1_CLK_ENABLE();
 
    /*##-2- Configure peripheral GPIO ##########################################*/
    /* SPI SCK GPIO pin configuration  */
 
    GPIO_InitStruct.Pin       = SPI_SCK_Pin;
    GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull      = GPIO_PULLUP;
    GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_MEDIUM;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
    HAL_GPIO_Init(SPI_SCK_GPIO_Port, &GPIO_InitStruct);
 
    // SPI MOSI GPIO pin configuration
    GPIO_InitStruct.Pin = SPI_MOSI_Pin;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
    HAL_GPIO_Init(SPI_MOSI_GPIO_Port, &GPIO_InitStruct);
 
    // SPI MISO GPIO pin configuration
    GPIO_InitStruct.Pin = SPI_MISO_Pin;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI2 ;
    HAL_GPIO_Init(SPI_MISO_GPIO_Port, &GPIO_InitStruct);
 
    // SPI CS GPIO pin configuration
    GPIO_InitStruct.Pin = SPI_CS_Pin;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
    GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP; 
    HAL_GPIO_Init(SPI_CS_GPIO_Port, &GPIO_InitStruct);
 
    // SPI master com trigger GPIO pin configuration(used to set NSS low on receiving slave mcu)
    GPIO_InitStruct.Pin = SPI_MASTER_TRIG_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP ;
    GPIO_InitStruct.Alternate = GPIO_AF0_SPI2;
    HAL_GPIO_Init(SPI_WIRELESS_MASTER_TRIG_Port, &GPIO_InitStruct)
 
 
    //##-3- Configure the DMA ##################################################
    // Configure the DMA handler for Transmission process
    hdma_tx.Instance                 = DMA1_Stream4;
    hdma_tx.Init.Channel             = DMA_CHANNEL_0;
    hdma_tx.Init.FIFOMode            = DMA_FIFOMODE_ENABLE;
    hdma_tx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
    hdma_tx.Init.MemBurst            = DMA_MBURST_INC8;
    hdma_tx.Init.PeriphBurst         = DMA_PBURST_INC8;
    hdma_tx.Init.Direction           = DMA_MEMORY_TO_PERIPH;
    hdma_tx.Init.PeriphInc           = DMA_PINC_DISABLE;
    hdma_tx.Init.MemInc              = DMA_MINC_ENABLE;
    hdma_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_tx.Init.MemDataAlignment    = DMA_MDATAALIGN_BYTE;
    hdma_tx.Init.Mode                = DMA_NORMAL;
    hdma_tx.Init.Priority            = DMA_PRIORITY_HIGH;
 
    result |= HAL_DMA_Init(&hdma_tx);
 
    /* Associate the initialized DMA handle to the the SPI handle */
    __HAL_LINKDMA(hspi, hdmatx, hdma_tx);
 
    /* Configure the DMA handler for Transmission process */
    hdma_rx.Instance                 = DMA1_Stream3;
    hdma_rx.Init.Channel             = DMA_CHANNEL_0;
    hdma_rx.Init.FIFOMode            = DMA_FIFOMODE_ENABLE;
    hdma_rx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
    hdma_rx.Init.MemBurst            = DMA_MBURST_INC8;
    hdma_rx.Init.PeriphBurst         = DMA_PBURST_INC8;
    hdma_rx.Init.Direction           = DMA_PERIPH_TO_MEMORY;
    hdma_rx.Init.PeriphInc           = DMA_PINC_DISABLE;
    hdma_rx.Init.MemInc              = DMA_MINC_ENABLE;
    hdma_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_rx.Init.MemDataAlignment    = DMA_MDATAALIGN_BYTE;
    hdma_rx.Init.Mode                = DMA_NORMAL;
    hdma_rx.Init.Priority            = DMA_PRIORITY_HIGH;
 
    result |= HAL_DMA_Init(&hdma_rx);
    if (result != HAL_OK) {
      result = HAL_OK;
    }
    /* Associate the initialized DMA handle to the the SPI handle */
    __HAL_LINKDMA(hspi, hdmarx, hdma_rx);
 
    /*##-4- Configure the NVIC for DMA #########################################*/
    /* NVIC configuration for DMA transfer complete interrupt (SPI2_TX) */
    HAL_NVIC_SetPriority(DMA1_Stream4_IRQn, 1, 0);
    HAL_NVIC_EnableIRQ(DMA1_Stream4_IRQn);
 
    /* NVIC configuration for DMA transfer complete interrupt (SPI2_RX) */
    HAL_NVIC_SetPriority(DMA1_Stream3_IRQn, 1, 0);
    HAL_NVIC_EnableIRQ(DMA1_Stream3_IRQn);
 
    HAL_NVIC_SetPriority(SPI2_IRQn, 1, 0);
    HAL_NVIC_EnableIRQ(SPI2_IRQn);

and this is my SPI handle setup:

pSpiHandle->Instance               = SPI2;
  pSpiHandle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
  pSpiHandle->Init.Direction         = SPI_DIRECTION_2LINES;
  pSpiHandle->Init.CLKPhase          = SPI_PHASE_1EDGE;
  pSpiHandle->Init.CLKPolarity       = SPI_POLARITY_HIGH;
  pSpiHandle->Init.DataSize          = SPI_DATASIZE_8BIT;
  pSpiHandle->Init.FirstBit          = SPI_FIRSTBIT_MSB;
  pSpiHandle->Init.TIMode            = SPI_TIMODE_DISABLE;
  pSpiHandle->Init.CRCCalculation    = SPI_CRCCALCULATION_ENABLE;
  pSpiHandle->Init.CRCPolynomial     = 7;
  pSpiHandle->Init.NSSPMode          = SPI_NSS_PULSE_DISABLED;
  pSpiHandle->Init.NSS               = SPI_NSS_HARD_INPUT;

the running code is then very simple:

//setup spi handle and run HAL_SPI_Init(pSpiHandle);
status = initSpiDmaHandle(&SpiHandle, SPI_MODE_MASTER) ;
 
 
HAL_GPIO_WritePin(SPI_MASTER_TRIG_Port, SPI_MASTER_TRIG_Pin, GPIO_PIN_RESET);
 
status |= HAL_SPI_TransmitReceive_DMA(&SpiHandle,(uint8_t*) aTxBuffer, (uint8_t*)aRxBuffer, BUFFERSIZE);
 

The slave is doing:

status = initSpiDmaHandle(&SpiHandle, SPI_MODE_SLAVE) ;
 
status |= HAL_SPI_TransmitReceive_DMA(&SpiHandle,(uint8_t*) aTxBuffer, (uint8_t*)aRxBuffer, BUFFERSIZE);

 before master starts its transmit/receive procedure

THE PROBLEM:

When both tx bufferts consist of "hello", everything works fine, but when i change it to "hello, THIS IS MASTER TESTING" / "hello, THIS IS SLAVE1 TESTING" i.e same sizes on both "sides"

the data is currupt and I only get part of the message(parts like "lo, " and then rubbish )

Anyone who has an Idéa on this?

4 REPLIES 4
TDK
Guru

Are the clocks exactly the same? Might want to make sure the slave clock is 2x of the master.

Can you see what's happening on the line? Logic analyzer or scope?

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

​@TDK​  Thank you for answer

Do you mean by setting prescaler? Changed it to this:

Master has setting pSpiHandle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;

Slave has setting pSpiHandle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;

but without improvement,

I also set GPIO speed for slave to GPIO_SPEED_FREQ_VERY_HIGH

Please see picture below from logic analyzer reading

The message is definitely improved but some letters are off and the start of the message is cut of for some reason

The messages sent is: "hello I am Master" and "hello I am Slave1"

 0693W000003QMDVQA4.png

Yes, exactly. The trace looks perfect, except that it’s not sending what you want. Not sure. I dont see any issues in the code that you posted. I would guess the issue is elsewhere.
If you feel a post has answered your question, please click "Accept as Solution".
MBohm
Associate II

The intresting thing is that while the trace looks like this, the message that gets put in the Rx buffer is "o\0\0\0 \0\0\0I\0\0\0 am M"

Could it have something to do with dma buffert/burst/memInc or datasize?

Turning DMA off, i.e. using HAL_SPI_TransmitReceive() instead of HAL_SPI_TransmitReceive_DMA() results in Rx buffer containing "hello I am SlavSe"

A great improvement but still not perfect.

But still, DMA settings seems to have something to do with it.