cancel
Showing results for 
Search instead for 
Did you mean: 

HAL_UART_Receive_IT enters error callback, and then never recovers from being busy

aaron1111
Associate II

Hi STM32 community,

I'm trying to process a UART string and interrupt when the full string is received. I'm having trouble receiving anything at all. To check that my serial terminal (PuTTY) settings are correct, I have tried HAL_UART_Transmit_IT(...) which transmits the correct string, and then calls its overridden callback.

When I try to do the same with HAL_UART_Receive_IT(...), the UART interrupt handler reports first UART_IT_ERR. I'm having difficulty understanding which ISR I should be checking to know which errors are happening - There is a RxISR, and also a Handle->ISR which report different statuses. I assumed that RxISR is the one I should be checking and clearing flags based on, however when I attempt to clear the flags by writing to ICR, they don't seem to be getting cleared.

If I check huart2.Instance->ISR, the binary value is 11000100000000011000000, which to me implies that bits 6 and 7 are enabled, (TXE and TC interrupts, when the transmitter is not even enabled...) However, If I check huart2->RxISR, the value is 1000000000000010011100110001

which implies parity error, idle error, receive not empty and others. I've basically just used CubeIDE to generate the config for UART, and written my own dodgy interrupt handler in an attempt to debug etc. Here is my main.c:

#include "main.h"
 
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART2_UART_Init(void);
 
UART_HandleTypeDef huart2;
uint8_t rx_buffer[2] = "zz";
uint8_t tx_buffer[13] = "Hello World\r\n";
 
void HAL_UART_RxCpltCallback (UART_HandleTypeDef *huart){
	HAL_UART_Receive_IT(&huart2, (uint8_t*) rx_buffer, 2);
}
 
void HAL_UART_TxCpltCallback (UART_HandleTypeDef *huart){
	HAL_UART_Transmit_IT(&huart2, (uint8_t*) tx_buffer, 13);
}
HAL_StatusTypeDef state2;
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart){
	//while(1);
	//HAL_UART_AbortReceive(&huart2);
	__HAL_UART_CLEAR_FLAG(&huart2,UART_CLEAR_FEF);
	__HAL_UART_SEND_REQ(&huart2, UART_RXDATA_FLUSH_REQUEST);
	HAL_UART_AbortReceive_IT(&huart2);
	state2 = HAL_UART_Receive_IT(&huart2, (uint8_t*) rx_buffer, 2);
}
 
int main(void)
{
  HAL_Init();
  /* Configure the system clock */
  SystemClock_Config();
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART2_UART_Init();
  HAL_Delay(500);
  HAL_StatusTypeDef state = HAL_UART_Receive_IT(&huart2, (uint8_t*)rx_buffer, 2);
  while (1)
  {
	  huart2.ErrorCode;
	  huart2.RxXferCount;
	  huart2.RxISR;
	  huart2.Instance->ISR;
	  huart2.gState;
	  huart2.RxState;
  }
}
 
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
 
  /** Configure the main internal regulator output voltage 
  */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
  RCC_OscInitStruct.MSIState = RCC_MSI_ON;
  RCC_OscInitStruct.MSICalibrationValue = 0;
  RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_5;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
  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();
  }
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART2;
  PeriphClkInit.Usart2ClockSelection = RCC_USART2CLKSOURCE_PCLK1;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }
}
 
static void MX_USART2_UART_Init(void)
{
  huart2.Instance = USART2;
  huart2.Init.BaudRate = 115200;
  huart2.Init.WordLength = UART_WORDLENGTH_8B;
  huart2.Init.StopBits = UART_STOPBITS_1;
  huart2.Init.Parity = UART_PARITY_NONE;
  huart2.Init.Mode = UART_MODE_TX_RX;
  huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart2) != HAL_OK)
  {
    Error_Handler();
  }
//	USART2->BRR = 160000 / 96; /* (1) */
//	USART2->CR1 = USART_CR1_RXNEIE | USART_CR1_RE | USART_CR1_UE; /* (2) */
}
 
static void MX_GPIO_Init(void)
{
 
  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOA_CLK_ENABLE();
 
}
 
void Error_Handler(void)
{
	while(1);
}
 
#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,
     tex: 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****/

Here is my interrupt handler

void USART2_IRQHandler(void){
	HAL_UART_IRQHandler(&huart2);
	if (__HAL_UART_GET_IT_SOURCE(&huart2, UART_IT_PE)){
		//while(1);
		__HAL_UART_CLEAR_PEFLAG(&huart2);
		USART2->ICR |= 1;
	}else if(__HAL_UART_GET_IT_SOURCE(&huart2, UART_IT_TXE)){
		//while(1);
	}else if(__HAL_UART_GET_IT_SOURCE(&huart2, UART_IT_TC)){
		//while(1);
	}else if(__HAL_UART_GET_IT_SOURCE(&huart2, UART_IT_RXNE)){
		//while(1);
	}else if(__HAL_UART_GET_IT_SOURCE(&huart2, UART_IT_IDLE)){
		while(1);
	}else if(__HAL_UART_GET_IT_SOURCE(&huart2, UART_IT_LBD)){
		while(1);
	}else if(__HAL_UART_GET_IT_SOURCE(&huart2, UART_IT_CTS)){
		while(1);
	}else if(__HAL_UART_GET_IT_SOURCE(&huart2, UART_IT_CM)){
		while(1);
	}else if(__HAL_UART_GET_IT_SOURCE(&huart2, UART_IT_WUF)){
		while(1);
	}else if(__HAL_UART_GET_IT_SOURCE(&huart2, UART_IT_ERR)){
		USART2->ICR |= 15;
		//while(1);
		//__HAL_UART_CLEAR_PEFLAG(&huart2);
	}else if(__HAL_UART_GET_IT_SOURCE(&huart2, UART_IT_ORE)){
		//while(1);
		USART2->ICR |= 8;
		__HAL_UART_CLEAR_OREFLAG(&huart2);
	}else if(__HAL_UART_GET_IT_SOURCE(&huart2, UART_IT_NE)){
		//while(1);
		USART2->ICR |= 4;
		__HAL_UART_CLEAR_NEFLAG(&huart2);
	}else if(__HAL_UART_GET_IT_SOURCE(&huart2, UART_IT_FE)){
		USART2->ICR |= 2;
		//while(1);
	}
}

What is the correct way to clear the interrupt flags and then start receiving strings? The most I've been able to do is receive a single null-terminating char as the first element... from there the RxStatus stays at 34 (busy). My application then gets stuck in the while(1) loop in main, which would be fine if the receives transfers were completing, but due to this, RxStatus will never change

Thanks for taking the time to read - any help would be greatly appreciated

0 REPLIES 0