cancel
Showing results for 
Search instead for 
Did you mean: 

UART DMA not work with STM32F767ZI and STM32F745VE

Kenji1
Senior

Hi Team

UART DMA not works with STM32F767ZI and STM32F745VE.

It does not transmit or receive data.

Testing same code with STM32F405 and STM32G474, UART DMA works fine.

Does anyone know why UART DMA doesn't work on STM32F?

Is there anything to be care of RAM setting when use UART DMA?

My dev. environment:

  • STM32CubeIDE Ver1.8.0
  • FW Package Ver: FW_F7 V1.16.2

Below is my test code.

※This code will not work unless the DMA and UART interrupts are enabled.

0693W00000KaLImQAN.png

main.c

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#define GETCHAR_PROTOTYPE int __io_getchar(void)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#define GETCHAR_PROTOTYPE int fgetc(FILE *f)
#endif /* __GNUC__ */
/* USER CODE END PD */
 
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
 
/* USER CODE END PM */
 
/* Private variables ---------------------------------------------------------*/
 
/* USER CODE BEGIN PV */
#define RX_BUFFER_SIZE (16)
#define TX_BUFFER_SIZE (16)
uint8_t rx_buffer[RX_BUFFER_SIZE];
uint8_t tx_buffer[TX_BUFFER_SIZE];
/* USER CODE END PV */
 
/* Private function prototypes -----------------------------------------------*/
 
int main(void)
{
  /* USER CODE BEGIN 1 */
 
  /* USER CODE END 1 */
 
  /* MCU Configuration--------------------------------------------------------*/
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* USER CODE BEGIN Init */
 
  /* USER CODE END Init */
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* USER CODE BEGIN SysInit */
 
  /* USER CODE END SysInit */
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */ 
  printf("%s\r\n", __DATE__);
  printf("%s\r\n", __TIME__);
 
  HAL_UART_Transmit_DMA(&huart2, (uint8_t*) "Hello World!!\r\n", 13);
  while (huart2.gState != HAL_UART_STATE_READY)
  {
     __NOP();
  }
 
  if (HAL_UART_Receive_DMA(&huart2, rx_buffer, 4) == HAL_ERROR)
  {
     __NOP();
  }
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
    __NOP();
  }
  /* USER CODE END 3 */
}
 
/* USER CODE BEGIN 4 */
PUTCHAR_PROTOTYPE
{
  __HAL_UART_FLUSH_DRREGISTER(&huart2);
  __HAL_UART_CLEAR_OREFLAG(&huart2);
 
  HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
 
  return ch;
}
 
GETCHAR_PROTOTYPE
{
  int ch;
 
  __HAL_UART_FLUSH_DRREGISTER(&huart2);
  __HAL_UART_CLEAR_OREFLAG(&huart2);
 
  HAL_UART_Receive(&huart2, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
 
  return ch;
}
/* USER CODE END 4 */

uart.c

/* USER CODE BEGIN 1 */
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{ 
  if (huart->Instance == USART2)
  {
      huart2.gState = HAL_UART_STATE_READY;
     __NOP();
  }
}
 
extern uint8_t rx_buffer[];
 
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  if (huart->Instance == USART2)
  {
    HAL_UART_Receive_DMA(&huart2, rx_buffer, 4);
    __NOP();
  }
}
 
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
  if (huart->Instance == USART2)
  {
    __NOP();
  }
}
/* USER CODE END 1 */

​linker for STM32F745VEH6

/*
******************************************************************************
**
** @file        : LinkerScript.ld
**
** @author      : Auto-generated by STM32CubeIDE
**
** @brief       : Linker script for STM32F745VEHx Device from STM32F7 series
**                      512Kbytes FLASH
**                      320Kbytes RAM
**
**                Set heap size, stack size and stack location according
**                to application requirements.
**
**                Set memory bank area and size if external memory is used
**
**  Target      : STMicroelectronics STM32
**
**  Distribution: The file is distributed as is, without any warranty
**                of any kind.
**
******************************************************************************
** @attention
**
** Copyright (c) 2022 STMicroelectronics.
** All rights reserved.
**
** This software is licensed under terms that can be found in the LICENSE file
** in the root directory of this software component.
** If no LICENSE file comes with this software, it is provided AS-IS.
**
******************************************************************************
*/
 
/* Entry Point */
ENTRY(Reset_Handler)
 
/* Highest address of the user mode stack */
_estack = ORIGIN(SRAM1) + LENGTH(SRAM1); /* end of "RAM" Ram type memory */
 
_Min_Heap_Size = 0x1000 ; /* required amount of heap */
_Min_Stack_Size = 0x1000 ; /* required amount of stack */
 
/* Memories definition */
MEMORY
{
  DTCM_RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K
  SRAM1    (xrw) : ORIGIN = 0x20010000, LENGTH = 240K
  SRAM2    (xrw) : ORIGIN = 0x2004C000, LENGTH = 16K
  ITCM_RAM (xrw) : ORIGIN = 0x00000000, LENGTH = 16K
  FLASH    (rx)  : ORIGIN = 0x08000000, LENGTH = 512K
}
 
/* Sections */
SECTIONS
{
  /* The startup code into "FLASH" Rom type memory */
  .isr_vector :
  {
    . = ALIGN(4);
    KEEP(*(.isr_vector)) /* Startup code */
    . = ALIGN(4);
  } >FLASH
 
  /* The program code and other data into "FLASH" Rom type memory */
  .text :
  {
    . = ALIGN(4);
    *(.text)           /* .text sections (code) */
    *(.text*)          /* .text* sections (code) */
    *(.glue_7)         /* glue arm to thumb code */
    *(.glue_7t)        /* glue thumb to arm code */
    *(.eh_frame)
 
    KEEP (*(.init))
    KEEP (*(.fini))
 
    . = ALIGN(4);
    _etext = .;        /* define a global symbols at end of code */
  } >FLASH
 
  /* Constant data into "FLASH" Rom type memory */
  .rodata :
  {
    . = ALIGN(4);
    *(.rodata)         /* .rodata sections (constants, strings, etc.) */
    *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
    . = ALIGN(4);
  } >FLASH
 
  .ARM.extab   : {
    . = ALIGN(4);
    *(.ARM.extab* .gnu.linkonce.armextab.*)
    . = ALIGN(4);
  } >FLASH
 
  .ARM : {
    . = ALIGN(4);
    __exidx_start = .;
    *(.ARM.exidx*)
    __exidx_end = .;
    . = ALIGN(4);
  } >FLASH
 
  .preinit_array     :
  {
    . = ALIGN(4);
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP (*(.preinit_array*))
    PROVIDE_HIDDEN (__preinit_array_end = .);
    . = ALIGN(4);
  } >FLASH
 
  .init_array :
  {
    . = ALIGN(4);
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT(.init_array.*)))
    KEEP (*(.init_array*))
    PROVIDE_HIDDEN (__init_array_end = .);
    . = ALIGN(4);
  } >FLASH
 
  .fini_array :
  {
    . = ALIGN(4);
    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP (*(SORT(.fini_array.*)))
    KEEP (*(.fini_array*))
    PROVIDE_HIDDEN (__fini_array_end = .);
    . = ALIGN(4);
  } >FLASH
 
  /* Used by the startup to initialize data */
  _sidata = LOADADDR(.data);
 
  /* Initialized data sections into "SRAM1" Ram type memory */
  .data :
  {
    . = ALIGN(4);
    _sdata = .;        /* create a global symbol at data start */
    *(.data)           /* .data sections */
    *(.data*)          /* .data* sections */
    *(.RamFunc)        /* .RamFunc sections */
    *(.RamFunc*)       /* .RamFunc* sections */
 
    . = ALIGN(4);
    _edata = .;        /* define a global symbol at data end */
 
  } >SRAM1 AT> FLASH
 
  /* Uninitialized data section into "SRAM1" Ram type memory */
  . = ALIGN(4);
  .bss :
  {
    /* This is used by the startup in order to initialize the .bss section */
    _sbss = .;         /* define a global symbol at bss start */
    __bss_start__ = _sbss;
    *(.bss)
    *(.bss*)
    *(COMMON)
 
    . = ALIGN(4);
    _ebss = .;         /* define a global symbol at bss end */
    __bss_end__ = _ebss;
  } >SRAM1
 
  /* User_heap_stack section, used to check that there is enough "SRAM1" Ram  type memory left */
  ._user_heap_stack :
  {
    . = ALIGN(8);
    PROVIDE ( end = . );
    PROVIDE ( _end = . );
    . = . + _Min_Heap_Size;
    . = . + _Min_Stack_Size;
    . = ALIGN(8);
  } >SRAM1
 
  /* Remove information from the compiler libraries */
  /DISCARD/ :
  {
    libc.a ( * )
    libm.a ( * )
    libgcc.a ( * )
  }
 
  .ARM.attributes 0 : { *(.ARM.attributes) }
}

1 ACCEPTED SOLUTION

Accepted Solutions
Kenji1
Senior

Hi everyone.

I found the cause of this problem.

There was STM32CubeIDE (CubeMX) generated code bug!

If UART is initialized before DMA, UART DMA will not work.

The UART should be initialized after DMA.

For example, this initialization sequence, UART DMA doesn't work.

/* Initialize all configured peripherals */
MX_UART4_Init();
MX_UART5_Init();
MX_DMA_Init();

And, this initialization sequence, UART DMA work.

/* Initialize all configured peripherals */
MX_DMA_Init();  
MX_UART4_Init();
MX_UART5_Init();

As far as I tested, behavior is same on STM32F4 / G4 / F7.

This is a bug of STM32CubeMX code generation.

I hope this will fix by STMicroelectronics.

View solution in original post

10 REPLIES 10
MM..1
Chief II

In MCU with more RAM memory area and MMU you need check if DMA have access to buffer.

And good practice is

volatile uint8_t rx_buffer[RX_BUFFER_SIZE];
volatile uint8_t tx_buffer[TX_BUFFER_SIZE];

And what is result from code showed??? Hang ? Work only printf ? ...

Hi MM..1 -san

Above code works with STM32G4 and STM32F4 MCU.

And UART transmit and receive function with DMA doesn't work with STM32F7 MCU.

In short, these functions not works, the others works.

  • HAL_UART_Transmit_DMA()
  • HAL_UART_Receive_DMA()

I want to use UART with DMA for transmit and receive data.

DDurk.1
Associate II

I had a similar issue, for me it was the interrupt priority settings on the NVIC tab under Pinout and Configuration in CubeMX. Lower numbers are higher priority. I would also check the clocks for the USARTS to make sure they are adequate, check the baud rates etc are the same and the GPIO speeds on the USARTS are adequate.

Kenji1
Senior

Hi everyone.

I found the cause of this problem.

There was STM32CubeIDE (CubeMX) generated code bug!

If UART is initialized before DMA, UART DMA will not work.

The UART should be initialized after DMA.

For example, this initialization sequence, UART DMA doesn't work.

/* Initialize all configured peripherals */
MX_UART4_Init();
MX_UART5_Init();
MX_DMA_Init();

And, this initialization sequence, UART DMA work.

/* Initialize all configured peripherals */
MX_DMA_Init();  
MX_UART4_Init();
MX_UART5_Init();

As far as I tested, behavior is same on STM32F4 / G4 / F7.

This is a bug of STM32CubeMX code generation.

I hope this will fix by STMicroelectronics.

Hi @Kenji​ ,

Glad to know that you found the solution to your issue.

But I would like to inform you that this is a known issue and fixed with STM32CubeMX 6.4.0.

But you may have a side effect in case you want to regenerate an old project with latest version of the tool.

Some more details on how to fix it in MX_DMA_Init order in the main.c file generated by STM32CubeMX, How to fix?

-Amel

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

This is first that i check , but you in question show code with valid order...

Hi @Amel NASRI​ 

I use this version of,

  • STM32CubeIDE: Version: 1.8.0 , Build: 11526_20211125_0815 (UTC)
  • STM32CubeMX: Version: 6.4.0-RC4, Build: 20211122-2105 (UTC)

It may be a known problem, but it hasn't been solved in CubMX6.4.0.

If it's a known problem and if you say that it have fixed,

please fix it well, and check before release CubeIDE or CubeMX software.

Also, it should give a warning, in case wrong initialization function calls.

About main.c, I fix [project manager]->[advanced settings]->[generated function calles] for code generation.

Hi @Kenji​ ,

Issue is fixed for projects created from scratch with CubeMX 6.4.0.

As explained in the question I shared previously, correct workaround is provided for projects cerated in a previous version with that issue. This is what you have already applied.

I add our STM32CubeMX expert @Sara BEN HADJ YAHYA​ in the loop of this discussion to take care of the improvement proposals you are suggesting.

-Amel

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Sara BEN HADJ YAHYA
ST Employee

Hello @Kenji​ ,

Thanks for your feedback,

Unfortunately this issue was partially fixed in v6.4.0. When creating a project from scratch (with DMA enabled), the order is generated correctly.

However, if we start project with no DMA, generate and then enable it, the order become wrong.

The Workaround is to always check the order in [project manager]->[advanced settings]->[generated function calls] before generating the code.

This issue will be properly fixed in the upcoming releases.

Sorry for the inconvenience it may cause.

About the warning proposition, I'll check internally with the team and see how we can address a modification. I will keep you posted with the updates.

Thanks @Amel NASRI​  for flagging this to us.

Sara.