cancel
Showing results for 
Search instead for 
Did you mean: 

Setting up DMA for UART on the H745 M4 Chip

ConfusedContrarian
Associate III

I'm trying to setup a GPS sensor (UBlox Max8Q) with a H745 Nucleo board using UART DMA using STM32CubeIDE. However, I’m having problems with setting up my board properly. My plan is to eventually do all my data acquisition on the M4 chip and do computation on the M7 but I can’t seem to find the write configuration for setting the memory area on the M4. I’ve set up my UART RX Stream for circular DMA

hdma_uart4_rx.Instance = DMA1_Stream0;
    hdma_uart4_rx.Init.Request = DMA_REQUEST_UART4_RX;
    hdma_uart4_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_uart4_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_uart4_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_uart4_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_uart4_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_uart4_rx.Init.Mode = DMA_CIRCULAR;
    hdma_uart4_rx.Init.Priority = DMA_PRIORITY_HIGH;
    hdma_uart4_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_uart4_rx) != HAL_OK)
    {
      Error_Handler();
    }

And I defined an area of memory in D2 RAM for my buffer

ALIGN_32BYTES(__attribute__((section (".RAM"))) char uart_buffer[128]) = {0};

My linker script has the following:

ENTRY(Reset_Handler)
 
/* Highest address of the user mode stack */
_estack = 0x10048000;    /* 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
{
FLASH (rx)      : ORIGIN = 0x08100000, LENGTH = 1024K
RAM (xrw)      : ORIGIN = 0x10000000, LENGTH = 288K
}
  /* used by the startup to initialize data */
  _sidata = LOADADDR(.data);
 
  /* Initialized data sections goes into RAM, load LMA copy after code */
  .data : 
  {
    . = ALIGN(4);
    _sdata = .;        /* create a global symbol at data start */
    *(.data)           /* .data sections */
    *(.data*)          /* .data* sections */
 
    . = ALIGN(4);
    _edata = .;        /* define a global symbol at data end */
  } >RAM AT> FLASH

I then start the UART receive in my main function

if(HAL_UART_Receive_DMA(&huart4, (uint8_t *)uart_buffer, 100)== HAL_OK)
  {
	  	//LED3_ON();
 
  }

But I run into the following problems:

I get no data at all into my buffer and the UART RX DMA function doesn’t seem to work. If I define a different section of memory, eg

ALIGN_32BYTES( __attribute__((section (".RAM_D3"))) uint8_t uart_buffer[128]) ={0};
 
/* Highest address of the user mode stack */
_estack = 0x10048000;    /* 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
{
FLASH (rx)      : ORIGIN = 0x08100000, LENGTH = 1024K
RAM (xrw)      : ORIGIN = 0x10000000, LENGTH = 288K
RAM_D3 (xrw)       : ORIGIN = 0x38000000, LENGTH = 64K
 
}

It works sometimes but takes multiple resets for the UART Receive to start working. I literally have to press reset on the Nucleo Board about 10 times to get it working once. Additionally, when it does work, the data isn’t aligned to the start of my array. ( I actually need only 100 bytes but if I’m not mistaken I think I can only do DMA alignment in powers of 2.

Can someone please let help? Some sort of Minimal Working Setup for the memory areas especially would be appreciated

2 REPLIES 2
TDK
Guru

Ensure DMA initialization is called before UART initialization.

I don't see any issues in the posted code.

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

Yeah, I initialise DMA before using either of the UARTs. I'm using USART3 without DMA and that;'s working without issues. UART4 RX is on PD0 while TX is on PA0 which is correct according to the datasheet. So I'm a bit stumped as to what may be causing the problem.