0

I'm working on an application where I process commands of fixed length received via UART.

I'm also using FreeRTOS and the task that handles the incoming commands is suspended until the uart interrupt handler is called, so my code is like this

void USART1_IRQHandler()
{
    HAL_UART_IRQHandler(&huart1);
}

void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart){
    HAL_UART_Receive_IT(&huart1, uart_rx_buf, CMD_LEN);
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){

    BaseType_t higherTaskReady = pdFALSE;

    HAL_UART_Receive_IT(&huart1, uart_rx_buf, CMD_LEN); //restart interrupt handler

    xSemaphoreGiveFromISR(uart_mutex, &higherTaskReady);
    portYIELD_FROM_ISR( higherTaskReady);   //Relase the semaphore
}

I am using the ErrorCallBack in case if an overflow occurs. Now I successfully catch every correct command, even if they are issued char by char.

However, I'm trying to make the system more error-proof by considering the case where more characters are received than expected.

The command length is 4 but if I receive, for example, 5 chars, then the first 4 is processed normally but when another command is received it starts from the last unprocessed char, so another 3 chars are needed until I can correctly process the commands again.

Luckily, the ErrorCallback is called whenever I receive more than 4 chars, so I know when it happens, but I need a robust way of cleaning the UART buffer so the previous chars are gone.

One solution I can think of is using UART receive 1 char at a time until it can't receive anymore, but is there a better way to simply flush the buffer?

EserRose
  • 142
  • 8
  • The proper solution is to first separate device operations (e.g. handling the interrupt) from processing the data (e.g. counting bytes of a message). Trying to do too much in what should be just a device driver (aka overloading the driver instead of separating and structuring/layering the code into more procedures and modules) seems to be a common flaw in bare-metal and/or microcontroller programming. – sawdust Aug 23 '21 at 06:01
  • *"However, I'm trying to make the system more error-proof by considering the case where more characters are received than expected."* -- Yes, make your program [robust](https://en.wikipedia.org/wiki/Robustness_(computer_science)). What happens if less than the expected number of character are received? – sawdust Aug 23 '21 at 06:11
  • @sawdust if less characters are received then it is stored in the buffer until a total of 4 characters are read, and then the command is processed. So less characters is not an issue – EserRose Aug 23 '21 at 06:38
  • That's not a robust scheme. You cannot assume that more characters are going to be received after the first three in any reasonable time interval. What if the cable was disconnected? Power removed from sending device? – sawdust Aug 23 '21 at 06:53
  • then i have to flush the buffer whether less or more chars are received – EserRose Aug 23 '21 at 07:19

1 Answers1

0

Yes, the problem is the lack of delimiter, because every byte can can carry a value to be processed from 0 to 255. So, how can you detect the inconsistency?
My solution is a checksum byte in the protocol. If the checksum fails, a blocking-mode UART_Receive function is called in order to put the rest of the data from the "system-buffer" to a "disposable-buffer". In my example the fix size of the protocol is 6, I use the UART6 and I have a global variable RxBuffer. Here is the code:

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
{
    if(UartHandle->Instance==USART6) {
        if(your_checksum_is_ok) {
            // You can process the incoming data
        } else {
            char TempBuffer;
            HAL_StatusTypeDef hal_status;
            do {
                hal_status = HAL_UART_Receive(&huart6, (uint8_t*)&TempBuffer, 1, 10);
            } while(hal_status != HAL_TIMEOUT);
        }
        HAL_UART_Receive_IT(&huart6, (uint8_t*)RxBuffer, 6);
    }
}
void HAL_UART_ErrorCallback(UART_HandleTypeDef *UartHandle) {
    if(UartHandle->Instance==USART6) {
        HAL_UART_Receive_IT(&huart6, (uint8_t*)RxBuffer, 6);
    }
}
HunKonrad
  • 1
  • 1