cancel
Showing results for 
Search instead for 
Did you mean: 

[SOLVED] STM32H7 SPI does not seem to work with DMA

Geo En
Associate III
Posted on March 07, 2018 at 13:01

EDIT: 14/03/2018

https://community.st.com/people/Schwaninger.Hannes

‌ found that we need to use RAM_D1 and not DTCMRAM of the memory area. This is not made by default when we use STM32CubeMx to set SPI and DMA together. Hello, I am working on a full duplex SPI communication through DMA using STM32H7. So, I have bought 2 NUCLEO-H743ZI, one to be the master, the other to be the slave. I have downloaded, built and flashed SPI_FullDuplex_ComDMA example via TrueStudio. As there is no ''TrueStudio format'' example, I have generated the project with STM32CubeMx and replace Inc and Src generated files with SPI_FullDuplex_ComDMAfiles. And tadada! ... It is not working correctly....... Only a few bytes are sent and Rxbuffer is never filled.

0690X00000609ynQAA.png

I have made connexion wires as short as possible and I have increased spi clock prescaler to get ''slow, nice and smooth'' signals. Electronic not seems to be the problem. I have modified the example to run it without DMA by replacing :

HAL_SPI_TransmitReceive_DMA(&SpiHandle, (uint8_t*)aTxBuffer, (uint8_t *)aRxBuffer, BUFFERSIZE)�?�?�?�?�?�?�?�?�?�?

With :

HAL_SPI_TransmitReceive(&SpiHandle, (uint8_t*)aTxBuffer, (uint8_t *)aRxBuffer, BUFFERSIZE,5000)�?�?�?�?�?�?�?�?�?�?

And now it's working! But not with the DMA .... This test shows that SPI is set and works correctly. aRxBuffer is filled with the good values.

0690X00000609w9QAA.png

Back in my code, I am trying now to send data through DMA with master and read them with slave:

// Master
HAL_SPI_Transmit_DMA(&SpiHandle, (uint8_t*)aTxBuffer, BUFFERSIZE)
// Slave
HAL_SPI_TransmitReceive(&SpiHandle, (uint8_t*)aTxBuffer, (uint8_t *)aRxBuffer, BUFFERSIZE, 5000)�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

It's working! Master sends DATA through DMA and my aRxBuffer is correctly filled on slave.

However, I have never been able to read DATA on master or slave with one of these functions:

HAL_SPI_TransmitReceive_DMA(&SpiHandle, (uint8_t*)aTxBuffer, (uint8_t *)aRxBuffer, BUFFERSIZE)
HAL_SPI_Receive_DMA(&SpiHandle, (uint8_t *)aRxBuffer, BUFFERSIZE)�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

I have tried to set DMA and SPI with STM32CubeMx but the problem remains the same. HAL_SPI_TransmitReceive_DMA always returns HAL_OK but code quickly falls into HAL_SPI_ErrorCallback. That only happens with DMA, never wih SPI only...

I do not think that I am doing something wrong as I have not modified the SPI_FullDuplex_ComDMA''example'' Src and Inc files...

EDIT: 13/03/2018

I have tried HAL_SPI_TransmitReceive_DMA and HAL_SPI_Receive_DMA on a STM32F7 to be sure that there is no technological problem on Cortex-M7. All DMA functions are working perfectly with F7.

EDIT: 14/03/2018

https://community.st.com/people/Schwaninger.Hannes

has tested SPI_FullDuplex_ComDMA example with Keil and it seems to work. However, he can't make it work with same configuration files if he creates a new project.

For me there is a problem with files generated by STM32CubeMX.

Does anyone have already made a full duplex spi communication with dma on a stm32h7 with a new STM32CubeMx project?

Thanks for your help!

#dma #spi #nucleo-h743zi #stm32h7 #hal
29 REPLIES 29
Posted on June 04, 2018 at 13:20

Great that you've got the SPI DMA transfer working ...

To your observations:

If you use the data cache you must clean the cache befor you send the new data with the function SCB_CleanDCache_by_Addr() . Otherwise you send the 'old data' (stored in the data cache) again and not the new data from the RAM.

Same thing with Rx buffers, but there you must call the funtion SCB_InvalidateDCache_by_Addr() that you see the new data in the buffer.

The second solution with active cache is to create a MPU region for the Rx/Tx data buffers.
Posted on July 12, 2018 at 05:19

I've been tearing my hair out trying to figure out why DMA simply wouldn't work on the H7, thank you so much for posting these explicit instructions!!

P.R.
Associate II

Was anybody able to get a SPI DMA Tx transfer working? I'm using CubeMx, TrueStudio, stm32H753 and was able to get a SPI DMA Rx transfer working. However, I am struggling to get the Tx working. It always ends with a SpiErrorCallback. Simply changing the RAM locations doesn't work for me either.

What does HAL_SPI_GetError() tell you?

P.R.
Associate II

It returns 0x10, which seems to be a DMA transfer error. I am not sure what the underlying problem might be.

It's probably better if you start your own thread (and include some code).

I have the same issue. I have DMA callback working on F7 , but same doesn't work on H7.

did you found the solution??

@sgand.16​  this solution worked for me

AAnt.1
Associate II

Hi to all!

@Geo En​  @Community member​ 

I have read this post, but could not understand how to edit code for DMA SPI transmit.

It is my post about problem https://community.st.com/s/question/0D53W00001atD9zSAE/stm32h7-spi-dma-not-working

I have STM32H745 nucleo. I want to use M4 core . In D2 domain i use SRAM1-SRAM3, DMA2 . I need to send data via SPI-DMA (SPI4, PE14 MOSI, DMA2_stream3, DMAUX11 ) I dont have any on MOSI pin + DMA2_IRQ_Handler don't work.

The same i have corectly did on stm32f407 - all worked good and spi dma transaction work.

Could you look my code and help me to edited SPI-DMA transaction ?

On STM32H745 i get correct work only SPI transmiting with out DMA

Could any body help me and explain how to solve my problem ?

Here i don't get helping about my problem https://community.st.com/s/article/FAQ-DMA-is-not-working-on-STM32H7-devices (((

Best regards

Hi to all! My old code:

https://community.st.com/s/question/0D53W00001atD9zSAE/stm32h7-spi-dma-not-working

I write modernized code - i could get only done function of IRQ_Handler, insite function LED switched, PD9 switched . That means - i can enter inside IRQ_handler and handler work, not stoped inside, but don't have any signal on MOSI SPI PIN .....

Me modernized code

function main.c

 DMA_HandleTypeDef hdma_tx;

   SPI_HandleTypeDef       SpiHandle;

#define TBS0 11

uint8_t TBuf0[TBS0]={0,1,2,3,4,5,6,7,8,9,11};

SPI_Configuration( );

.....

 while (1)

 {

   HAL_DMA_Start_IT(&hdma_tx, *TBuf0,(uint32_t) &(SPI4->TXDR),TBS0);

}

function for SPI_DMA init

#define VIDEO_DMA            DMA2

#define DMA_STREAM              DMA2_Stream3

#define DMA_CHANNEL             DMA_Channel_3

void SPI_Configuration( void ) 

{

   GPIO_InitTypeDef        GPIO_InitStructure;     

// RCC->AHB2ENR |= (RCC_AHB2ENR_D2SRAM1EN | RCC_AHB2ENR_D2SRAM2EN | RCC_AHB2ENR_D2SRAM3EN);  // Enable the SRAM

//   __HAL_RCC_D2SRAM1_CLK_ENABLE();

//   __HAL_RCC_D2SRAM2_CLK_ENABLE();

//   __HAL_RCC_D2SRAM3_CLK_ENABLE();

   #define SPI4_FORCE_RESET()              __HAL_RCC_SPI4_FORCE_RESET()

 #define SPI4_RELEASE_RESET()            __HAL_RCC_SPI4_RELEASE_RESET()

 #define SPIx                            SPI4 

   #define SPIx_MOSI_GPIO_CLK_ENABLE()     __HAL_RCC_GPIOE_CLK_ENABLE()

   #define SPIx_CLK_ENABLE()               __HAL_RCC_SPI4_CLK_ENABLE()

 #define DMAx_CLK_ENABLE()               __HAL_RCC_DMA2_CLK_ENABLE()

   SPI4_FORCE_RESET();

   SPI4_RELEASE_RESET();

      HAL_DMA_DeInit(&hdma_tx);

   // ##-1- Enable peripherals and GPIO Clocks #################################

 // Enable GPIO TX/RX clock

 SPIx_MOSI_GPIO_CLK_ENABLE();

 // Enable SPI1 clock

 SPIx_CLK_ENABLE();

 // Enable DMA clock

 DMAx_CLK_ENABLE();

    // Common configuration for all channels

 GPIO_InitStructure.Pin = GPIO_PIN_14 | GPIO_PIN_12; // PE12 SPI SCK

   GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;

 GPIO_InitStructure.Pull = GPIO_NOPULL;

 GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;

 GPIO_InitStructure.Alternate = GPIO_AF5_SPI4;

 HAL_GPIO_Init(GPIOE, &GPIO_InitStructure);

 // ##-3- Configure the DMA

 // Configure the DMA handler for Transmission process

 hdma_tx.Instance                = DMA_STREAM; // SPI4 maybe?

 hdma_tx.Init.FIFOMode           = DMA_FIFOMODE_DISABLE;

 hdma_tx.Init.FIFOThreshold      = DMA_FIFO_THRESHOLD_FULL;

 hdma_tx.Init.MemBurst           = DMA_MBURST_SINGLE;

 hdma_tx.Init.PeriphBurst        = DMA_PBURST_SINGLE;

 hdma_tx.Init.Request            = DMA_REQUEST_SPI4_TX;

 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_CIRCULAR; //DMA_NORMAL;  // ????? 

 hdma_tx.Init.Priority           = DMA_PRIORITY_HIGH; // ????

 HAL_DMA_Init(&hdma_tx);

 // ##-1- Configure the SPI peripheral

 // Set the SPI parameters

 SpiHandle.Instance              = SPI4;

 SpiHandle.Init.Mode             = SPI_MODE_MASTER;

 SpiHandle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16; 

 SpiHandle.Init.Direction        = SPI_DIRECTION_2LINES_TXONLY;

 SpiHandle.Init.CLKPhase         = SPI_PHASE_2EDGE;

 SpiHandle.Init.CLKPolarity      = SPI_POLARITY_LOW;

 SpiHandle.Init.DataSize         = SPI_DATASIZE_8BIT;

 SpiHandle.Init.FirstBit         = SPI_FIRSTBIT_MSB;

 SpiHandle.Init.TIMode           = SPI_TIMODE_DISABLE;

 SpiHandle.Init.CRCCalculation   = SPI_CRCCALCULATION_DISABLE;

 SpiHandle.Init.CRCPolynomial    = 7;

 SpiHandle.Init.CRCLength        = SPI_CRC_LENGTH_8BIT;

 SpiHandle.Init.NSS              = SPI_NSS_SOFT;

 SpiHandle.Init.NSSPMode         = SPI_NSS_PULSE_DISABLE;

 SpiHandle.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_ENABLE; 

 HAL_SPI_Init(&SpiHandle);

 // ##-4- Configure the NVIC for DMA

 // NVIC configuration for DMA transfer complete interrupt (SPI4_TX)

 HAL_NVIC_SetPriority(DMA_INTERRUPT, 1, 1); //DMA2_Stream3_IRQn

 HAL_NVIC_EnableIRQ(DMA_INTERRUPT);  //  DMA2_Stream3_IRQn

}

Function for INTERRUPT and switching PIN inside

void DMA2_Stream3_IRQHandler(void)

{   

   HAL_DMA_IRQHandler(&hdma_tx);

   HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0); // LD1 blinky

   HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_9); // PD9 blinky

}

If i understand, DMA start to work, because interrupt handler worked, but DMA don'nt send any signal to MOSI PE14 pin.....

Best regards.