2024-10-16 02:11 PM - edited 2024-10-16 02:14 PM
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.
Solved! Go to Solution.
2024-10-16 05:16 PM
Of course. Just strcpy(data5678, "abcdefg");
and no tinkering with startup, linker script or whatever.
2024-10-16 03:34 PM - edited 2024-10-16 03:35 PM
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.
2024-10-16 04:46 PM
Is there some method we need to call to initialize the array in D2? For your reference, here are the functions that are called in the ellipsis on line 20 (in order):
- __HAL_RCC_D2SRAM1_CLK_ENABLE() (we have also tried with __HAL_RCC_D2SRAM2_CLK_ENABLE, it doesn't affect the result)
- MPU_Config()
- HAL_Init()
- SystemClock_Config()
- MX_GPIO_Init()
- MX_DMA_Init()
- MX_FDCAN1_Init()
- MX_USART3_UART_Init()
(Everything but the call to enable the RAM is generated by CubeMX.)
For the second point, we've tried every combination of cacheable/noncacheable and bufferable/nonbufferable but no luck there.
Thank you for your help!
2024-10-16 05:16 PM
Of course. Just strcpy(data5678, "abcdefg");
and no tinkering with startup, linker script or whatever.