cancel
Showing results for 
Search instead for 
Did you mean: 

Configuring Memory for STM32H753ZI USART DMA

cttewari
Visitor

Hi,

We have been trying to setup DMA USART3 with the STM32H753ZI Nucleo.

We would like to keep our stack in DTCMRAM and we thought we could move the USART buffer into SRAM1 or SRAM2 since DMA1 and DMA2 have access to it, following this post.

We edited our GCC linker file to have a section in RAM_D2 for the buffer. We also configured the MPU to write-through the buffer region on RAM_D2 to prevent DCache from interfering with the DMA. This did not work, we tried multiple buffer positions and MPU configurations and none of them worked.

 

/* Highest address of the user mode stack */
_estack = ORIGIN(DTCMRAM) + LENGTH(DTCMRAM);    /* end of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x200;      /* required amount of heap  */
_Min_Stack_Size = 0x400; /* required amount of stack */

/* Specify the memory areas */
MEMORY
{
DTCMRAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 128K
RAM (xrw)      : ORIGIN = 0x24000000, LENGTH = 512K
RAM_D2 (xrw)      : ORIGIN = 0x30000000, LENGTH = 288K
RAM_D3 (xrw)      : ORIGIN = 0x38000000, LENGTH = 64K
ITCMRAM (xrw)      : ORIGIN = 0x00000000, LENGTH = 64K
FLASH (rx)      : ORIGIN = 0x8000000, LENGTH = 2048K
}
/* Define output sections */
SECTIONS
{
...
  .buffer (NOLOAD) :
  {
    *(.dma_buffer)
  } >RAM_D2
...
}
void MPU_Config(void)
{
  MPU_InitStruct.Enable = MPU_REGION_ENABLE;
  MPU_InitStruct.Number = MPU_REGION_NUMBER0;
  MPU_InitStruct.BaseAddress = 0x30000000;
  MPU_InitStruct.Size = MPU_REGION_SIZE_128B;
  MPU_InitStruct.SubRegionDisable = 0x0;
  MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
  MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
  MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
  MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
  MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
  MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
}
...
uint8_t data5678[8] __attribute__((section(".dma_buffer"))) = "abcdefg";
...
int main(void)
{
  ...
  uint32_t test1234 = 8;
  ptr = &test1234;
  while (1)
  {
    HAL_UART_Transmit_DMA(&huart3, data5678, test1234);
    HAL_Delay(1000);

    dma_error_code = hdma_usart3_tx.ErrorCode;
    uart_error_code = huart3.ErrorCode;
    uart_gstate = huart3.gState;
    GPIO_SET(LED_YELLOW, dma_error_code == 0);
    (void)(dma_error_code);

    if(HAL_GetTick() < 0)
    test1234 += 1;
  }
  ...
}

 


We noticed that the only way we could get the DMA to actually send the messages and not hang on UART TX was by moving the top of the stack to the end of RAM instead of DTCMRAM (_estack = ORIGIN(RAM) + LENGTH(RAM);). We could then remove the buffer allocation and DMA would work without issues.

We would really like to not have to move the stack into SRAM since we want the performance of keeping it on DTCMRAM. It's unclear why the solution above isn't working through and we've tried many permutations of the configurations in the steps above.

 

1 REPLY 1
Pavel A.
Evangelist III

Just few points...

* Array data5678 in RAM_D2 section won't be initialized before TX. Can you guess why? (but it should contain the expected string if placed in the default data section.)

* In MPU_Config line 12 you define it CACHEABLE so it still will be cacheable for read. Maybe you want non-cacheable.