2026-01-26 5:35 AM - last edited on 2026-01-26 6:12 AM by mƎALLEm
Hello everyone,
First of all I am kinda new in ARM (I never use), I am working on the STM32H745I-DISCO board (using the CM7 core) and I am facing a persistent issue with UART . No matter what I try, the RX Interrupt never triggers, and the code never enters the HAL_UART_RxCpltCallback.
My Setup: Board: STM32H745I-DISCO
IDE: STM32CubeIDE (Latest Version)
Scenario: UART Loopback Test (Connecting TX to RX physically).
Peripheral: USART6 (TX: PC6 / RX: PC7) on the Arduino Headers (D1/D0).
Settings: 115200 baud, 8N1, Asynchronous.
The Problem:
-HAL_UART_Transmit works fine (signals observed). HAL_UART_Receive_IT returns HAL_OK. However, the HAL_UART_RxCpltCallback is never executed. When checking SFRs in Debug mode: RXNE flag stays at 0.
What I have verified so far (Step-by-Step):
NVIC Settings: USART6 global interrupt is Enabled in CubeMX.
Vector Table: USART6_IRQHandler exists in stm32h7xx_it.c and calls HAL_UART_IRQHandler.
Initialization Order: I ensured that MX_USART6_UART_Init() is called BEFORE HAL_UART_Receive_IT in main.c.
Cache Management: I know H7 has cache coherence issues, so I completely Disabled D-Cache (SCB_DisableDCache()) at the beginning of main() to avoid DMA/Buffer issues (even though I am using IT, not DMA).
Hardware: Tested with a jumper wire between PC6 and PC7. I also tried different UART pins (like UART3 VCP), but the result is the same.(Also I tried another pins and UARTx or USARTy )
HardFault: Previously I had HardFaults due to init order, but that is fixed. The code runs, the while(1) loop blinks the LED, but no interrupt occurs.
Can someone help me?
Solved! Go to Solution.
2026-01-28 2:07 AM
Hello,
It seems the VCP connection has been changed from the board rev B01 to B02 from USART3 to USART1:
Rev B01:
Rev B02. and starting from Rev 2, USART1 is used with VCP instead of USART3:
So check the revision of your board:
If B02 or later you need to use USART1. I've attached a project where USART1 is used and Tx and Rx are looped back and the Rx callback is continuously called each character is received.
Hope that helps.
2026-01-26 6:12 AM - edited 2026-01-26 6:12 AM
Hello @EnesUNLU and welcome to the ST community,
As you can see from the board schematic, PC6 and PC7 are not exported on the Arduino header. Tx and Rx are exported on D0/D1 (PB10/PB11) on CN6 connector:
So for now use USART3 and connect PB10/PB11 together.
PC6 and PC7 are already used by the eMMC memory:
2026-01-26 6:51 AM
Thanks for the fast reply, I tried what you said and since last 3 days I am tryng to solve this problem and I have tried all rx/tx pins. IBut I cannot do it. Maybe my board is burned or?
2026-01-26 6:57 AM
Please select one configuration and retest: select USART3 and connect PB10 to PB11.
If it doesn't work you can share your code with that configuration i.e. USART3 using PB10 and PB11.
2026-01-26 7:15 AM - edited 2026-01-26 7:15 AM
Hello @EnesUNLU
Could you please confirm whether the HAL_UART_TxCpltCallback is being executed in your application?
This will help us verify that the transmit interrupt path is working correctly.
In addition, could you check the TX line with a logic analyzer or oscilloscope to confirm that the data is actually being transmitted on the pin?
2026-01-26 7:28 AM
Before adding the complication of interrupts, have you got this working using just blocking calls ?
Getting the simple blocking calls working first will demonstrate that your basic hardware setup is working - then you can move on to working with interrupts ...
2026-01-27 10:27 PM
Thank you for helping me,
I already add some code (Toggle the LEDs) for ensuring the hardware is working. I add LED toggle code for CM7 then I add another LED code for CM4 these codes are working.
When I add HAL_UART_TxCpltCallback and I cannot confirm that HAL_UART_TxCpltCallback is being executed. I changed USART6 to USART3 as you guys said. As I said I have never used dual core or memory management CPU so maybe I couldn't saw a basic problem. (Again my goal is the getting loop answer from UART Tx to Rx after that I will use DMA and then rs232 but I even cannot done UART :D)
Here is my code for CM7 (the includes which in USER Begin Includes is working while I am trying I add these here and configure the files and nothing changed):
----------------------------------------------------------------------------------------------------------------------------------------------------------
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @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 "main.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stm32h7xx_hal_uart_ex.h"
#include "stm32h7xx_hal_uart.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* DUAL_CORE_BOOT_SYNC_SEQUENCE: Define for dual core boot synchronization */
/* demonstration code based on hardware semaphore */
/* This define is present in both CM7/CM4 projects */
/* To comment when developping/debugging on a single core */
#define DUAL_CORE_BOOT_SYNC_SEQUENCE
#if defined(DUAL_CORE_BOOT_SYNC_SEQUENCE)
#ifndef HSEM_ID_0
#define HSEM_ID_0 (0U) /* HW semaphore 0*/
#endif
#endif /* DUAL_CORE_BOOT_SYNC_SEQUENCE */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
UART_HandleTypeDef huart3;
/* USER CODE BEGIN PV */
uint8_t send_data[] = "Test\n";
uint8_t receive_data[10];
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART3_UART_Init(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* USER CODE BEGIN Boot_Mode_Sequence_0 */
#if defined(DUAL_CORE_BOOT_SYNC_SEQUENCE)
int32_t timeout;
#endif /* DUAL_CORE_BOOT_SYNC_SEQUENCE */
/* USER CODE END Boot_Mode_Sequence_0 */
/* USER CODE BEGIN Boot_Mode_Sequence_1 */
#if defined(DUAL_CORE_BOOT_SYNC_SEQUENCE)
/* Wait until CPU2 boots and enters in stop mode or timeout*/
timeout = 0xFFFF;
while((__HAL_RCC_GET_FLAG(RCC_FLAG_D2CKRDY) != RESET) && (timeout-- > 0));
if ( timeout < 0 )
{
Error_Handler();
}
#endif /* DUAL_CORE_BOOT_SYNC_SEQUENCE */
/* USER CODE END Boot_Mode_Sequence_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 Boot_Mode_Sequence_2 */
#if defined(DUAL_CORE_BOOT_SYNC_SEQUENCE)
/* When system initialization is finished, Cortex-M7 will release Cortex-M4 by means of
HSEM notification */
/*HW semaphore Clock enable*/
__HAL_RCC_HSEM_CLK_ENABLE();
/*Take HSEM */
HAL_HSEM_FastTake(HSEM_ID_0);
/*Release HSEM in order to notify the CPU2(CM4)*/
HAL_HSEM_Release(HSEM_ID_0,0);
/* wait until CPU2 wakes up from stop mode */
timeout = 0xFFFF;
while((__HAL_RCC_GET_FLAG(RCC_FLAG_D2CKRDY) == RESET) && (timeout-- > 0));
if ( timeout < 0 )
{
Error_Handler();
}
#endif /* DUAL_CORE_BOOT_SYNC_SEQUENCE */
/* USER CODE END Boot_Mode_Sequence_2 */
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART3_UART_Init();
/* USER CODE BEGIN 2 */
// H7 Serisinde Debug yaparken değişkenlerin anlık güncellendiğini görmek için
// (Opsiyonel ama önerilir, yoksa Live Expression bazen geç güncellenir)
//SCB_DisableDCache();
// UART7'yi kesme modunda başlat. 9 byte gelince kesmeye girecek.
if(HAL_UART_Receive_IT(&huart3, receive_data, 5) != HAL_OK)
{
// Hata varsa buraya düşer
Error_Handler();
}
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
HAL_GPIO_TogglePin(GPIOI, GPIO_PIN_13); // LED Yanıp sönsün
HAL_Delay(500);
HAL_UART_Transmit(&huart3, send_data, 5, 100);
if (HAL_UART_Receive_IT(&huart3, send_data, 1) == HAL_BUSY) {
if (huart3.ErrorCode != HAL_UART_ERROR_NONE) {
HAL_UART_AbortReceive(&huart3);
HAL_UART_Receive_IT(&huart3, send_data, 1);
}
}
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Supply configuration update enable
*/
HAL_PWREx_ConfigSupply(PWR_DIRECT_SMPS_SUPPLY);
/** Configure the main internal regulator output voltage
*/
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 5;
RCC_OscInitStruct.PLL.PLLN = 160;
RCC_OscInitStruct.PLL.PLLP = 2;
RCC_OscInitStruct.PLL.PLLQ = 4;
RCC_OscInitStruct.PLL.PLLR = 4;
RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_2;
RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
RCC_OscInitStruct.PLL.PLLFRACN = 0;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
|RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief USART3 Initialization Function
* @PAram None
* @retval None
*/
static void MX_USART3_UART_Init(void)
{
/* USER CODE BEGIN USART3_Init 0 */
/* USER CODE END USART3_Init 0 */
/* USER CODE BEGIN USART3_Init 1 */
/* USER CODE END USART3_Init 1 */
huart3.Instance = USART3;
huart3.Init.BaudRate = 9600;
huart3.Init.WordLength = UART_WORDLENGTH_8B;
huart3.Init.StopBits = UART_STOPBITS_1;
huart3.Init.Parity = UART_PARITY_NONE;
huart3.Init.Mode = UART_MODE_TX_RX;
huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart3.Init.OverSampling = UART_OVERSAMPLING_16;
huart3.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart3.Init.ClockPrescaler = UART_PRESCALER_DIV1;
huart3.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart3) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetTxFifoThreshold(&huart3, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetRxFifoThreshold(&huart3, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_DisableFifoMode(&huart3) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART3_Init 2 */
/* USER CODE END USART3_Init 2 */
}
/**
* @brief GPIO Initialization Function
* @PAram None
* @retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOI_CLK_ENABLE();
__HAL_RCC_GPIOF_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOI, GPIO_PIN_13, GPIO_PIN_RESET);
/*Configure GPIO pin : PB8 */
GPIO_InitStruct.Pin = GPIO_PIN_8;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF8_UART4;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/*Configure GPIO pins : PC7 PC6 */
GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF7_USART6;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/*Configure GPIO pin : PI13 */
GPIO_InitStruct.Pin = GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOI, &GPIO_InitStruct);
/*Configure GPIO pins : PF6 PF7 */
GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_UART7;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
/* USER CODE BEGIN MX_GPIO_Init_2 */
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOD_CLK_ENABLE(); // PD8 ve PD9 için D portu saatini açıyoruz
/*Configure GPIO pins : PD8 PD9 */
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // Alternatif Fonksiyon Modu
GPIO_InitStruct.Pull = GPIO_NOPULL; // Genelde boşta bırakılır (Gerekirse PULLUP)
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; // UART hızı için LOW yeterlidir
GPIO_InitStruct.Alternate = GPIO_AF7_USART3; // USART3 için AF7 seçilmeli
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
/* USER CODE END MX_GPIO_Init_2 */
}
/* USER CODE BEGIN 4 */
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) {
if(huart->ErrorCode & HAL_UART_ERROR_ORE) {
// Overrun hatası oluştu!
// Genelde hata bayrağını temizlemek ve RX'i restart etmek gerekir.
__HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF);
}
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
// USART6'dan veri geldiyse
if(huart->Instance == USART3)
{
HAL_UART_Receive_IT(&huart3, receive_data, 5);
}
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART3)
{
HAL_UART_Receive_IT(&huart3, receive_data, 5);
}
}
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @PAram file: pointer to the source file name
* @PAram line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
2026-01-27 10:40 PM
While I am searching functions in HAL I saw that "HAL_UART_Transmit_IT" function and I changed "HAL_UART_Transmit_IT(&huart3, send_data, 5)" instead of "HAL_UART_Transmit(&huart3, send_data, 5)" after that I can see in debug the HAL_UART_TxCpltCallback function is working and the debug is running like that = HAL_UART_Transmit_IT => HAL_UART_TxCpltCallback => UART_EndTransmit_IT => HAL_UART_IRQHandler =>USART3_IRQHandler => main while loop
2026-01-27 10:46 PM
On the H745 DISCO make sure USART6 is actually clocked and assigned to the CM7 core (RCC + SYSCFG boot/core assignment), otherwise RXNE will never assert. Also confirm HAL_UART_Receive_IT() is called again inside HAL_UART_RxCpltCallback() — the interrupt only fires once unless re-armed.
2026-01-27 11:08 PM
Thanks for advice, maybe your suggestion is my solution,
if(huart->Instance == USART3)
{
// ORE (Overrun) gibi hatalar oluşursa bayrakları temizle ve dinlemeyi tekrar başlat
uint32_t er = HAL_UART_GetError(huart);
if(er & HAL_UART_ERROR_ORE) __HAL_UART_CLEAR_OREFLAG(huart);
if(er & HAL_UART_ERROR_NE) __HAL_UART_CLEAR_NEFLAG(huart);
if(er & HAL_UART_ERROR_FE) __HAL_UART_CLEAR_FEFLAG(huart);
// Tekrar başlat
HAL_UARTEx_ReceiveToIdle_IT(&huart3, receive_data, sizeof(receive_data));
}I add this code and I saw in debug that "er = 4" which is equal HAL_UART_ERROR_FE but I cannot understand I am using same UART Rx and Tx so same I should have same baudrate (9600) and configurations how can I get Frame error ? Is it related with RCC or Clock? I checked what you said but I choose cortex-7 for USART3 (I changed USART6 to USART3)