cancel
Showing results for 
Search instead for 
Did you mean: 

Working with Receive Timeout(RTOIE) and RXNEIE simultaneously

srikanth977
Associate

Hi,

Board details : NUCLEO64 - G071RBTX

I am trying to understand Receive timeout interrupt for implementation of Modbus RTU using USART2. As a start, to check the receive timeout interrupt, i want to check with a 2 seconds timeout interrupt. So configured the RTOR register accordingly below (Please guide if i configured wrong)

===

USART2 CONFIGURATIONS:

BAUD=19200

All other bits at default

===

Steps I used additionally after code generation (HAL) Below steps are written after HAL configures the USART2.

  1. Enabled RXNEIE interrupt
  2. Enabled RTOIE interrupt
  3. Enabled Receive timeout (USART2->RTOEN bit is set)
  4. Configured RTOR register with value 3840002 (To see interrupt of after 2 seconds)

Calculation for RTOR = (2000000/ 0.520833). I refered the calculation from here

static void MX_USART2_UART_Init(void)
{
 
  /* USER CODE BEGIN USART2_Init 0 */
 
  /* USER CODE END USART2_Init 0 */
 
  /* USER CODE BEGIN USART2_Init 1 */
 
  /* USER CODE END USART2_Init 1 */
  huart2.Instance = USART2;
  huart2.Init.BaudRate = 19200;
  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.Init.ClockPrescaler = UART_PRESCALER_DIV1;
  huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart2) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetTxFifoThreshold(&huart2, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetRxFifoThreshold(&huart2, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_DisableFifoMode(&huart2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART2_Init 2 */
  //By default Receive interrupt is not enabled
 
  //Enable Receive interrupt and receive timeout of USART2
  USART2->CR1 |=(1<<26U) | (1<<5U);
 
  USART2->CR2 |=(1<<23U);	//RECEIVER TIMEOUT ENABLE
  USART2->RTOR=3840002u;
 
  /* USER CODE END USART2_Init 2 */
 
}

Finally in USART2 IRQ handler below is the code:

One more thing in the IRQ handler, i checked with each bit. Is this the correct method?

void USART2_IRQHandler(void)
{
  /* USER CODE BEGIN USART2_IRQn 0 */
 
 
if((USART2->ISR && 32u))
{
	  unsigned char test=USART2->RDR;
	  //USART2->ICR |=(1<<11u);	//CLEAR RTOF BIT
}
else if ((USART2->ISR && 2048u))
{
	//ENTERED RTOF
	unsigned char tester;
	tester=0u;
	USART2->ICR |=(1<<11u);	//CLEAR RTOF BIT
}
  /* USER CODE END USART2_IRQn 0 */
  HAL_UART_IRQHandler(&huart2);
  /* USER CODE BEGIN USART2_IRQn 1 */
 
  /* USER CODE END USART2_IRQn 1 */
}

Interrupt does not occur after about 2 seconds. Please guide me.

1 ACCEPTED SOLUTION

Accepted Solutions
Panchev68
Senior

Are you sure this is correct?

if((USART2->ISR && 32u))
{
//...//
}
else if ((USART2->ISR && 2048u))
{
 
}

Maybe that's what you meant

if((USART2->ISR & 32u))
{
//...//
}
else if ((USART2->ISR & 2048u))
{
 
}

This is my procedure for continuously receiving a sequence of characters.

static uint8_t _RxChar;
static void _receiveAgain(UART_HandleTypeDef *uart_ptr);
 
/// initialization
void begin (UART_HandleTypeDef *uart_ptr)
{
    //.....//
    // 1st time
    _receiveAgain(uart_ptr);
}
 
/// override `HAL_UART_RxCpltCallback`
extern "C" void HAL_UART_RxCpltCallback(UART_HandleTypeDef *uart_ptr)
{
    assert(uart_ptr);
 
    // isr code here...
 
    // the received character is in `_RxChar`
    _receiveAgain(uart_ptr);
}
/// override `HAL_UART_TxCpltCallback`
extern "C" void HAL_UART_ErrorCallback(UART_HandleTypeDef * uart_ptr)
{
    assert(uart_ptr);
 
    auto err = HAL_UART_GetError(uart_ptr);
 
    if (err & (HAL_UART_ERROR_ORE | HAL_UART_ERROR_FE | HAL_UART_ERROR_NE | HAL_UART_ERROR_PE))
    {
        __HAL_UART_CLEAR_FLAG(uart_ptr, UART_IT_ERR);
        
        //
        // isr code here...
        //
        _receiveAgain(uart_ptr);    // receive again
    }
}
 
static void _receiveAgain(UART_HandleTypeDef *uart_ptr)
{
	assert(uart_ptr);
	uart_ptr->pRxBuffPtr = &_RxChar;
	uart_ptr->RxXferSize = 1;
	uart_ptr->RxXferCount = 1;
	uart_ptr->ErrorCode = HAL_UART_ERROR_NONE;
 
	// Check if a transmit process is ongoing or not
	if (uart_ptr->RxState == HAL_UART_STATE_BUSY_TX) uart_ptr->RxState = HAL_UART_STATE_BUSY_TX_RX;
	else uart_ptr->RxState = HAL_UART_STATE_BUSY_RX;
 
	__HAL_UNLOCK(uart_ptr);
	__HAL_UART_ENABLE_IT(uart_ptr, UART_IT_PE);
	__HAL_UART_ENABLE_IT(uart_ptr, UART_IT_ERR);
	__HAL_UART_ENABLE_IT(uart_ptr, UART_IT_RXNE);
}

View solution in original post

3 REPLIES 3
Pavel A.
Evangelist III

RTO interrupt occurs only after at least one byte is received. If no data has been received during specified time, this interrupt won't trigger.

Usually you want to use RTO interrupt together with DMA.

RXNE interrupt lets you to receive and handle incoming data as soon as possible.

On the opposite, the purpose of RTO is to delay handling of the data until RX ends.

And DMA stores received data with minimal latency. Meanwhile the CPU is free for other tasks.

So you don't need RXNE and RTO interrupts together, unless you want something more complicated.

-- pa

Panchev68
Senior

Are you sure this is correct?

if((USART2->ISR && 32u))
{
//...//
}
else if ((USART2->ISR && 2048u))
{
 
}

Maybe that's what you meant

if((USART2->ISR & 32u))
{
//...//
}
else if ((USART2->ISR & 2048u))
{
 
}

This is my procedure for continuously receiving a sequence of characters.

static uint8_t _RxChar;
static void _receiveAgain(UART_HandleTypeDef *uart_ptr);
 
/// initialization
void begin (UART_HandleTypeDef *uart_ptr)
{
    //.....//
    // 1st time
    _receiveAgain(uart_ptr);
}
 
/// override `HAL_UART_RxCpltCallback`
extern "C" void HAL_UART_RxCpltCallback(UART_HandleTypeDef *uart_ptr)
{
    assert(uart_ptr);
 
    // isr code here...
 
    // the received character is in `_RxChar`
    _receiveAgain(uart_ptr);
}
/// override `HAL_UART_TxCpltCallback`
extern "C" void HAL_UART_ErrorCallback(UART_HandleTypeDef * uart_ptr)
{
    assert(uart_ptr);
 
    auto err = HAL_UART_GetError(uart_ptr);
 
    if (err & (HAL_UART_ERROR_ORE | HAL_UART_ERROR_FE | HAL_UART_ERROR_NE | HAL_UART_ERROR_PE))
    {
        __HAL_UART_CLEAR_FLAG(uart_ptr, UART_IT_ERR);
        
        //
        // isr code here...
        //
        _receiveAgain(uart_ptr);    // receive again
    }
}
 
static void _receiveAgain(UART_HandleTypeDef *uart_ptr)
{
	assert(uart_ptr);
	uart_ptr->pRxBuffPtr = &_RxChar;
	uart_ptr->RxXferSize = 1;
	uart_ptr->RxXferCount = 1;
	uart_ptr->ErrorCode = HAL_UART_ERROR_NONE;
 
	// Check if a transmit process is ongoing or not
	if (uart_ptr->RxState == HAL_UART_STATE_BUSY_TX) uart_ptr->RxState = HAL_UART_STATE_BUSY_TX_RX;
	else uart_ptr->RxState = HAL_UART_STATE_BUSY_RX;
 
	__HAL_UNLOCK(uart_ptr);
	__HAL_UART_ENABLE_IT(uart_ptr, UART_IT_PE);
	__HAL_UART_ENABLE_IT(uart_ptr, UART_IT_ERR);
	__HAL_UART_ENABLE_IT(uart_ptr, UART_IT_RXNE);
}

Panchev68
Senior

 I hope I was useful