cancel
Showing results for 
Search instead for 
Did you mean: 

Problems with UART Interrupt Receive

Sany
Associate III

Hello, i have a STM32F407VET6 MCU and i have problems with UART3 and Interrupt Receive, it does not work.

UART3 is connected with a Display, my MCU sends every Second a "PING" and the Display answers with "PONG", that works fine.

Global Interrupt for UART3 is enabled, with Prio 1.

With a Serialadapter, i see the "PING", and the "PONG" answer, but the Interrupt is not working/fired.

What i do wrong? Is there a problem with RTOS?

UART_HandleTypeDef huart3;
uint8_t uartData[64];
 
/* Definitions for hmiTask */
osThreadId_t hmiTaskHandle;
const osThreadAttr_t hmiTask_attributes = {
  .name = "hmiTask",
  .stack_size = 1024 * 4,
  .priority = (osPriority_t) osPriorityBelowNormal,
};
 
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart == &huart3)
	{
		HAL_UART_Receive_IT(&huart3, uartData, sizeof(uartData));
	}
}
 
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_ADC1_Init();
  MX_CAN1_Init();
  MX_I2C1_Init();
  MX_RTC_Init();
  MX_SDIO_SD_Init();
  MX_SPI1_Init();
  MX_USART3_UART_Init();
  MX_USART6_UART_Init();
  MX_FATFS_Init();
  MX_TIM2_Init();
  MX_CRC_Init();
 
  /* Initialize interrupts */
  MX_NVIC_Init();
  /* USER CODE BEGIN 2 */
  HAL_TIM_Base_Start(&htim2);
  HAL_ADC_Start(&hadc1);
  initGpio();
 
  HAL_UART_Receive_IT(&huart3, uartData, sizeof(uartData));
  /* USER CODE END 2 */
 
  /* Init scheduler */
  osKernelInitialize();
 
  /* USER CODE BEGIN RTOS_MUTEX */
  /* add mutexes, ... */
  /* USER CODE END RTOS_MUTEX */
 
  /* USER CODE BEGIN RTOS_SEMAPHORES */
  /* add semaphores, ... */
  /* USER CODE END RTOS_SEMAPHORES */
 
  /* USER CODE BEGIN RTOS_TIMERS */
  /* start timers, add new ones, ... */
  /* USER CODE END RTOS_TIMERS */
 
  /* USER CODE BEGIN RTOS_QUEUES */
  /* add queues, ... */
 
  /* USER CODE END RTOS_QUEUES */
 
  /* Create the thread(s) */
  /* creation of defaultTask */
  defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);
 
  /* creation of radioTask */
  radioTaskHandle = osThreadNew(radioTaskFunc, NULL, &radioTask_attributes);
 
  /* creation of hmiTask */
  hmiTaskHandle = osThreadNew(hmiTaskFunc, NULL, &hmiTask_attributes);
 
  /* creation of batteryMeas */
  batteryMeasHandle = osThreadNew(battTask, NULL, &batteryMeas_attributes);
 
  /* USER CODE BEGIN RTOS_THREADS */
  /* add threads, ... */
  /* USER CODE END RTOS_THREADS */
 
  /* USER CODE BEGIN RTOS_EVENTS */
  /* add events, ... */
 
  RFM23 *rfm23 = new RFM23();
 
  if(!rfm23->init())
  {
	  while(true)
	  {
		  HAL_GPIO_WritePin(LED_ERROR_GPIO_Port, LED_ERROR_Pin, GPIO_PIN_SET);
		  delay_us(200);
		  HAL_GPIO_WritePin(LED_ERROR_GPIO_Port, LED_ERROR_Pin, GPIO_PIN_RESET);
	  }
  }
 
  	HAL_GPIO_WritePin(LED_LINK_TX_GPIO_Port, LED_LINK_TX_Pin, GPIO_PIN_SET);
  	HAL_GPIO_WritePin(LED_LINK_RX_GPIO_Port, LED_LINK_RX_Pin, GPIO_PIN_SET);
  	delay_us(350);
  	HAL_GPIO_WritePin(LED_LINK_TX_GPIO_Port, LED_LINK_TX_Pin, GPIO_PIN_RESET);
  	HAL_GPIO_WritePin(LED_LINK_RX_GPIO_Port, LED_LINK_RX_Pin, GPIO_PIN_RESET);
 
  	/* creation of radioTask */
  	  radioTaskHandle = osThreadNew(radioTaskFunc, NULL, &radioTask_attributes);
 
  /* USER CODE END RTOS_EVENTS */
 
  /* 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 */
}
 
/**
  * @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 = 115200;
  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;
  if (HAL_UART_Init(&huart3) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART3_Init 2 */
 
  /* USER CODE END USART3_Init 2 */
 
}
 
/* USER CODE BEGIN Header_hmiTaskFunc */
/**
* @brief Function implementing the hmiTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_hmiTaskFunc */
void hmiTaskFunc(void *argument)
{
  /* USER CODE BEGIN hmiTaskFunc */
  /* Infinite loop */
 
	while(true)
  {
		if(!displayPresent)
		{
			uint8_t data[] = "PING;;;;;";
			HAL_UART_Transmit_IT(&huart3, data, sizeof(data));
			osDelay(1000);
		}
  }
  /* USER CODE END hmiTaskFunc */
}

7 REPLIES 7

> the Interrupt is not working/fired.

How do you know?

Some general hints to debug "interrupt not firing" here.

JW

Sany
Associate III

Thank you but this help me not.

Sany
Associate III

Hello,

I tested a little bit with the buffer size, when i decrease the buffersize under 6 bytes, then the interrupt is working and fired.

When i increase the buffersize over > 6, the interrupt is fired one time and then never, after restart the MCU are it works again for one time..

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2023 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
 
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
 
/* USER CODE END Includes */
 
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
 
/* USER CODE END PTD */
 
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
 
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
 
/* USER CODE END PM */
 
/* Private variables ---------------------------------------------------------*/
UART_HandleTypeDef huart1;
 
/* USER CODE BEGIN PV */
 
/* USER CODE END PV */
 
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART1_UART_Init(void);
/* USER CODE BEGIN PFP */
 
/* USER CODE END PFP */
 
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
uint8_t buffer[6];
 
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	uint8_t pong[6] = "PING\r\n";
    HAL_UART_Transmit(&huart1, pong, sizeof(pong), 100);
    HAL_UART_Receive_IT(&huart1, buffer, 6);
}
/* USER CODE END 0 */
 
/**
  * @brief  The application entry point.
  * @retval int
  */
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_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
 
  HAL_UART_Receive_IT(&huart1, buffer, sizeof(buffer));
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
	  uint8_t ping[6] = "PONG\r\n";
	  HAL_UART_Transmit(&huart1, ping, sizeof(ping), 100);
	  HAL_Delay(500);
    /* 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};
 
  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  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_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
 
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
}
 
/**
  * @brief USART1 Initialization Function
  * @param None
  * @retval None
  */
static 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;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART1_Init 2 */
 
  /* USER CODE END USART1_Init 2 */
 
}
 
/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
 
  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOA_CLK_ENABLE();
 
}
 
/* USER CODE BEGIN 4 */
 
/* 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 */
 
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

I debugged the code with a larger buffer (16), i send 'test' to my device, then the USART1_IRQHandler(void) is fired, in this function is:

    /* UART Over-Run interrupt occurred --------------------------------------*/
    if (((isrflags & USART_SR_ORE) != RESET) && (((cr1its & USART_CR1_RXNEIE) != RESET) || ((cr3its & USART_CR3_EIE) != RESET)))
    {
      huart->ErrorCode |= HAL_UART_ERROR_ORE;
    }

The function sets the ErrorCode HAL_UART_ERROR_ORE and this is why the interrupt not executed after one time....

Whats the Problem, or what i do wrong?

sizeof() is not appropriate for NUL terminated strings.

Use strlen() as appropriate.

Make sure the buffer is large enough to contain the NUL.

Your use of blocking functions in the callback (interrupt) context is poor, and can result in it not being ready to receive data as it arrives.

Your first example, unclear what the triggering event is.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Sany
Associate III

Hello,

Thanks for the Tip with sizeof()...

Hm, the Buffer has a size of 64, when buffer is full, the interrupt is fired, but the problem is, the IRQ Handler Runs in Error 0x08 (HAL_UART_ERROR_ORE).

But why runs the IRQ handler in the overrun? my test message is with \r\n 6 signs long, the buffer are 64..

i dont unterstand that, is that a bug in HAL?

>>But why runs the IRQ handler in the overrun?

Because you block for 6 character times in the callback.

This causes an RX interrupt due to the RX failing

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Karl Yamashita
Lead II

A couple of things I see wrong.

  • You're transmitting from inside an interrupt and it's also a blocking function. When you're in an interrupt, you should save the data or set a flag, then get out. Then check the flag or data in a polling routine and then you can transmit.
  • You're not checking HAL return status so when you call HAL_UART_Receive_IT and it does not return HAL_OK, then the receive interrupt was not enabled. It'll never receive an interrupt when new characters come in, ever. What you have to do is set a flag if status is not HAL_OK, then in a polling routine check if the flag is set. If it is then you know Receive interrupt is not enable, so you clear the flag and make a call HAL_UART_Receive_IT again while still looking at HAL status and setting a flag if once again it does not return HAL_OK.

You can check this post where I pasted some code

https://community.st.com/s/question/0D53W000022Hi9ySAC/stm32-hal-uart-receive-interrupt-stops-receiving-at-random-times

If you find my answers useful, click the accept button so that way others can see the solution.