Skip to main content
Associate II
August 10, 2026
Question

stm32N6 usart Configuration DMA Cyclic Receiving

  • August 10, 2026
  • 4 replies
  • 54 views

When I was using STM32N6, I tried to generate USART with STM32CubeMx, but when you enable DCache the DMA did not properly handle USART-RX data.


The USART startup code is as follows
 



static FIXED_DMA_USER_RAM uint8_t s_ulDebugUsartRxDmaFifo[16];

bool DevUsartInit(void) {
bool ret = false;
//HAL_UART_DeInit(&huart1);
//MX_USART1_UART_Init();
memset(s_ulDebugUsartRxDmaFifo, 0, sizeof(s_ulDebugUsartRxDmaFifo));
if (HAL_UARTEx_ReceiveToIdle_DMA(&huart1, s_ulDebugUsartRxDmaFifo, sizeof(s_ulDebugUsartRxDmaFifo)) == HAL_OK) {
ret = true;
}
__DSB();
return ret;
}

/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{

/* USER CODE BEGIN 1 */
/* USER CODE END 1 */

/* MPU Configuration--------------------------------------------------------*/
MPU_Config();

/* Enable the CPU Cache */

/* Enable I-Cache---------------------------------------------------------*/
SCB_EnableICache();

/* Enable D-Cache---------------------------------------------------------*/
SCB_EnableDCache();

/* MCU Configuration--------------------------------------------------------*/
HAL_Init();

/* USER CODE BEGIN Init */

/* USER CODE END Init */

/* USER CODE BEGIN SysInit */

/* USER CODE END SysInit */

/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_GPDMA1_Init();
MX_USART1_UART_Init();
MX_TIM2_Init();
SystemIsolation_Config();
/* USER CODE BEGIN 2 */
DevUsartInit();
/* USER CODE END 2 */

/* Init scheduler */
osKernelInitialize();
/* Call init function for freertos objects (in app_freertos.c) */
MX_FREERTOS_Init();

/* Start scheduler */
osKernelStart();

/* We should never get here as control is now taken by the scheduler */

/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}

/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file usart.c
* @brief This file provides code for the configuration
* of the USART instances.
******************************************************************************
* @attention
*
* Copyright (c) 2026 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.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "usart.h"

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

UART_HandleTypeDef huart1;
DMA_HandleTypeDef handle_GPDMA1_Channel1;
DMA_NodeTypeDef Node_GPDMA1_Channel0;
DMA_QListTypeDef List_GPDMA1_Channel0;
DMA_HandleTypeDef handle_GPDMA1_Channel0;

/* USART1 init function */

void MX_USART1_UART_Init(void)
{

/* USER CODE BEGIN USART1_Init 0 */

/* USER CODE END USART1_Init 0 */

/* USER CODE BEGIN USART1_Init 1 */

/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetTxFifoThreshold(&huart1, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetRxFifoThreshold(&huart1, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_DisableFifoMode(&huart1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART1_Init 2 */

/* USER CODE END USART1_Init 2 */

}

void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{

GPIO_InitTypeDef GPIO_InitStruct = {0};
DMA_NodeConfTypeDef NodeConfig= {0};
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
if(uartHandle->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspInit 0 */

/* USER CODE END USART1_MspInit 0 */

/** Initializes the peripherals clock
*/
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USART1;
PeriphClkInitStruct.Usart1ClockSelection = RCC_USART1CLKSOURCE_CLKP;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
Error_Handler();
}

/* USART1 clock enable */
__HAL_RCC_USART1_CLK_ENABLE();

__HAL_RCC_GPIOE_CLK_ENABLE();
/**USART1 GPIO Configuration
PE5 ------> USART1_TX
PE6 ------> USART1_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

GPIO_InitStruct.Pin = GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

/* USART1 DMA Init */
/* GPDMA1_REQUEST_USART1_TX Init */
handle_GPDMA1_Channel1.Instance = GPDMA1_Channel1;
handle_GPDMA1_Channel1.Init.Request = GPDMA1_REQUEST_USART1_TX;
handle_GPDMA1_Channel1.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
handle_GPDMA1_Channel1.Init.Direction = DMA_PERIPH_TO_MEMORY;
handle_GPDMA1_Channel1.Init.SrcInc = DMA_SINC_INCREMENTED;
handle_GPDMA1_Channel1.Init.DestInc = DMA_DINC_FIXED;
handle_GPDMA1_Channel1.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_BYTE;
handle_GPDMA1_Channel1.Init.DestDataWidth = DMA_DEST_DATAWIDTH_BYTE;
handle_GPDMA1_Channel1.Init.Priority = DMA_LOW_PRIORITY_LOW_WEIGHT;
handle_GPDMA1_Channel1.Init.SrcBurstLength = 1;
handle_GPDMA1_Channel1.Init.DestBurstLength = 1;
handle_GPDMA1_Channel1.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT0;
handle_GPDMA1_Channel1.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
handle_GPDMA1_Channel1.Init.Mode = DMA_NORMAL;
if (HAL_DMA_Init(&handle_GPDMA1_Channel1) != HAL_OK)
{
Error_Handler();
}

__HAL_LINKDMA(uartHandle, hdmatx, handle_GPDMA1_Channel1);

/* GPDMA1_REQUEST_USART1_RX Init */
NodeConfig.NodeType = DMA_GPDMA_LINEAR_NODE;
NodeConfig.Init.Request = GPDMA1_REQUEST_USART1_RX;
NodeConfig.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
NodeConfig.Init.Direction = DMA_PERIPH_TO_MEMORY;
NodeConfig.Init.SrcInc = DMA_SINC_FIXED;
NodeConfig.Init.DestInc = DMA_DINC_INCREMENTED;
NodeConfig.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_BYTE;
NodeConfig.Init.DestDataWidth = DMA_DEST_DATAWIDTH_BYTE;
NodeConfig.Init.SrcBurstLength = 1;
NodeConfig.Init.DestBurstLength = 1;
NodeConfig.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT0;
NodeConfig.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
NodeConfig.Init.Mode = DMA_NORMAL;
NodeConfig.TriggerConfig.TriggerPolarity = DMA_TRIG_POLARITY_MASKED;
NodeConfig.TriggerConfig.TriggerSelection = GPDMA1_TRIGGER_GPDMA1_CH0_TCF;
NodeConfig.DataHandlingConfig.DataExchange = DMA_EXCHANGE_NONE;
NodeConfig.DataHandlingConfig.DataAlignment = DMA_DATA_RIGHTALIGN_ZEROPADDED;
NodeConfig.SrcSecure = DMA_CHANNEL_SRC_SEC;
NodeConfig.DestSecure = DMA_CHANNEL_DEST_SEC;
if (HAL_DMAEx_List_BuildNode(&NodeConfig, &Node_GPDMA1_Channel0) != HAL_OK)
{
Error_Handler();
}

if (HAL_DMAEx_List_InsertNode(&List_GPDMA1_Channel0, NULL, &Node_GPDMA1_Channel0) != HAL_OK)
{
Error_Handler();
}

if (HAL_DMAEx_List_SetCircularMode(&List_GPDMA1_Channel0) != HAL_OK)
{
Error_Handler();
}

handle_GPDMA1_Channel0.Instance = GPDMA1_Channel0;
handle_GPDMA1_Channel0.InitLinkedList.Priority = DMA_LOW_PRIORITY_LOW_WEIGHT;
handle_GPDMA1_Channel0.InitLinkedList.LinkStepMode = DMA_LSM_FULL_EXECUTION;
handle_GPDMA1_Channel0.InitLinkedList.LinkAllocatedPort = DMA_LINK_ALLOCATED_PORT0;
handle_GPDMA1_Channel0.InitLinkedList.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
handle_GPDMA1_Channel0.InitLinkedList.LinkedListMode = DMA_LINKEDLIST_CIRCULAR;
if (HAL_DMAEx_List_Init(&handle_GPDMA1_Channel0) != HAL_OK)
{
Error_Handler();
}

if (HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel0, &List_GPDMA1_Channel0) != HAL_OK)
{
Error_Handler();
}

__HAL_LINKDMA(uartHandle, hdmarx, handle_GPDMA1_Channel0);

/* USART1 interrupt Init */
HAL_NVIC_SetPriority(USART1_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(USART1_IRQn);
/* USER CODE BEGIN USART1_MspInit 1 */

/* USER CODE END USART1_MspInit 1 */
}
}

void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{

if(uartHandle->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspDeInit 0 */

/* USER CODE END USART1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_USART1_CLK_DISABLE();

/**USART1 GPIO Configuration
PE5 ------> USART1_TX
PE6 ------> USART1_RX
*/
HAL_GPIO_DeInit(GPIOE, GPIO_PIN_5|GPIO_PIN_6);

/* USART1 DMA DeInit */
HAL_DMA_DeInit(uartHandle->hdmatx);
HAL_DMA_DeInit(uartHandle->hdmarx);

/* USART1 interrupt Deinit */
HAL_NVIC_DisableIRQ(USART1_IRQn);
/* USER CODE BEGIN USART1_MspDeInit 1 */

/* USER CODE END USART1_MspDeInit 1 */
}
}

/* USER CODE BEGIN 1 */

/* USER CODE END 1 */



 

4 replies

KDJEM.1
ST Technical Moderator
August 11, 2026

Hello ​@xukong ;

 

Are you get the same issue when testing an available example UART_ReceptionToIdle_CircularDMA?

Could you please share the ioc file?

I think the SystemClock_Config is missing in your code.

 

Thank you.

Kaouthar

To give better visibility on the answered topics, please click on "Best answer" on the reply which solved your issue or answered your question.
xukongAuthor
Associate II
August 11, 2026

I've already found the problem, but I still don't know why. If you're sure, could you please let me know?

The problem lies below:
 

First solution:  

    SCB_DisableDCache();
if (HAL_UARTEx_ReceiveToIdle_DMA(&huart1, s_ulDebugUsartRxDmaFifo, sizeof(s_ulDebugUsartRxDmaFifo)) == HAL_OK) {
ret = true;
}
SCB_EnableDCache();

Second solution:

 

DMA_NodeTypeDef Node_GPDMA1_Channel0;


This variable should have no buffering.
 

xukongAuthor
Associate II
August 11, 2026
KDJEM.1
ST Technical Moderator
August 14, 2026

Hello ​@xukong ;

 

Which STM32N6 revision are you using : Rev.Z or Rev.B?

To check the device marking, please refer to “Reference device marking schematics for STM32 microcontrollers and microprocessors” (TN1433).

 

Thank you.

Kaouthar

To give better visibility on the answered topics, please click on "Best answer" on the reply which solved your issue or answered your question.