Showing results for 
Search instead for 
Did you mean: 

STM32F7 DMA fails to write to SRAM

Associate II
Posted on April 19, 2016 at 15:05

We've ran into a very strange DMA issue recently as we have been expanding our code. We noticed this problem after adding some new libraries which use up a lot of ram, which caused our existing spi+dma drivers stop working correctly (even though the new code was completely independent, and never executed!)

After a couple days of investigating i'm able to determine reproduce the condition of this problem, but am still baffled as to why its occuring. The problem is that our SPI+DMA transfers no longer works when the RX/TX buffer are located in the SRAM instead of the DTCMRAM. In order to highlight this issue, I've implemented the following test code: - I changed the linker script so that all of the code is placed in the SRAM, but with a CCRAM ram section declaration

/* Specify the memory areas */
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
RAM (xrw) : ORIGIN = 0x20010000, LENGTH = 240k
CCMRAM (rw) : ORIGIN = 0x20000000, LENGTH = 64K

- I have a test task which periodically reads a register value on our sensor using the SPI bus. The TX/RX buffers are global variables, and i can change their ram location using the ''__attribute__((section(''.ccmram'')))'' attribute.

//uint8_t tx_buffer[10] __attribute__((section(''.ccmram''))) = {0};
//uint8_t rx_buffer[10] __attribute__((section(''.ccmram''))) = {0};
uint8_t tx_buffer[10];
uint8_t rx_buffer[10];
void test_task(void *pvParameters)
spi_ms5611_send(tx_buffer, rx_buffer, 3, RXTX, portMAX_DELAY);

- The spi function is defined as:

uint8_t spi_ms5611_send(uint8_t* tx_buffer, uint8_t* rx_buffer,
uint32_t n_bytes, spi_direction_t direction, uint32_t timeout)
uint8_t return_flag = 1;
// Enable chip select
// Start spi transfer using appropriate hal function
case TX:
HAL_SPI_Transmit_DMA(&g_hspi_baro, tx_buffer, n_bytes);
case RX:
HAL_SPI_Receive_DMA(&g_hspi_baro, rx_buffer, n_bytes);
case RXTX:
HAL_SPI_TransmitReceive_DMA(&g_hspi_baro, tx_buffer, rx_buffer, n_bytes);
// Wait for Transmit to complete
return_flag = xSemaphoreTake(g_spi_baro_rx_dma_semaphore, timeout);
// Release chip select
return return_flag;

We are using FreeRTOS and the send function blocks on a semaphore. the semaphore is released in theHAL_SPI_TxRxCpltCallback. Observations: - When the Tx/Rx buffers are placed in the DTCMRAM (0x20000000) everything works as it should. However, if i remove the __attribute(..), placing the buffers in the SRAM (0x20010000), the code executes completely (the dma callbacks are called, etc). but the RX buffer is never written to. - RX buffer is filled with 0xAB before performing the spi transaction, and the values do not change. this shows that the DMA is not writing the values to the memory. - I've compared both cases using an oscilloscope, and the spi lines are identical in both cases. The MOSI/MISO/CLK/CSN lines are active and contain the proper data. - If i use the ''HAL_SPI_TransmitReceive'' (which uses interrupts) instead of ''HAL_SPI_TransmitReceive_DMA'', it works in both cases. - I've played with the SPI clock, as well as the overall system clocks, to no effect. I found nothing in the datasheet, reference manual, or errata sheet which would indicate why i am having this issue. Everything indicated We desperately need some feedback in order to solve this issue. Thanks, Alex Pabouctsidis
Posted on April 19, 2016 at 15:30

SRAM is accessed through AXI, and is likely to be cached.

Do you have an ''MPU_Config'' function in your project that set the region cached ?

So either avoid to use that region for DMA, or manage cache invalidation/flush by yourself, or run with no caches at all (beware the loss of performance).