Reception of characters via UART interrupt [FreeRTOS - Cortex M7]

xavierpacheco wrote on Tuesday, March 13, 2018:

Hello,

I am using STM32CubeMx to solve the following issue:

My system should avoid loss of character reception, and since I can not guarantee the priority of the task that invokes my services, the reception of characters will be handled by an interrupt routine that is activated when a character is received by the serial port.

This routine must save the received characters in a certain data structure (buffer) to be later processed by the tasks (tasks) of the system. Processing of this interrupt routine should be minimal so as not to interfere with other interrupt routines or tasks.

The routines used by the tasks are:

 char uart_getchar (void) - this routine reads a character from the buffer where the characters have been received and should not return until a character is obtained.

 bool uart_getchar_available (char * c) - this routine returns a boolean value determining if a buffer character could be read, in which case the value is found in parameter c. If there is no character in the buffer, the routine returns immediately and the result of the call is false.

The way I’m implementing this is as follows:

This will be my ISR in stm32f7xx_it.c:

extern uint8_t buffRX[10];

void USART3_IRQHandler(void)
{
  HAL_UART_IRQHandler(&huart3);
  HAL_UART_Receive_IT(&huart3, buffRX, 10);

}

Part of the main:

#include "main.h"
#include "stm32f7xx_hal.h"
#include "cmsis_os.h"
UART_HandleTypeDef huart3;

osThreadId defaultTaskHandle; //task for char uart_getchar (void) (normal priority)
osThreadId myTask02Handle; //task for bool uart_getchar_available (char * c) (normal priority)

uint8_t buffRX[10];

How could I implement char uart_getchar (void) and bool uart_getchar_available (char * c) in my tasks? Can I use HAL_UART_RxCpltCallback to check if a caracter has been obtained? Also, do you think that I have initialized the UART interrupt correctly? I’m not expert using STM32 MCUs, that’s why I ask for your suggestions.

rtel wrote on Tuesday, March 13, 2018:

I’m not 100% sure what you are asking, but I think you are looking for
advice on creating a blocking UART driver. There are lots of FreeRTOS
features that could be used for this, but I would recommend looking at
stream buffers as a start. Your UART interrupt handler need just write
the characters into the stream buffer. Your receiving task need only
block on the stream buffer until it contains characters. If you also
need a function that returns the number of bytes available you can just
query the stream buffer to see how many bytes it contains.

https://www.freertos.org/RTOS-stream-buffer-example.html

Regarding your set up of the UART interrupt. If you use a FreeRTOS API
then the priority of the interrupt needs to be at or below
configMAX_SYSCALL_INTERRUPT_PRIORITY, and as you are using an STM32,
there is an extra step to ensure all the priority bits are set to be
preemption priority and not sub priority. That part is explained on
this page: https://www.freertos.org/RTOS-Cortex-M3-M4.html

richard_damon wrote on Thursday, March 15, 2018:

My first comment is I haven’t looked at the STM32CubeMX routines in particular, but my general impression with a lot of these ‘bare metal’ abstraction drivers is they DON’T mesh well with an RTOS, inpart because they often don’t provide easy ways to block and reactivate.

With the sort of getchar routines you are looking to use, you really want to put the data in a Queue, or with V10 a StreamBuffer, and that says you want a driver that in the ISR is given the characters as received so you can place them in the Queue/Buffer, not one that does it’s own buffering (as then you can’t easly get the blocking behavior).

What I often end up using is a single function, int getChar(TickType_t), which I pass a timeout value (0 would be like your uart_getchar_available operation, or portMAX_DELAY for a full block until one arrives) and have the function return the character (as an unsigned char, 00-255) if one was received, and -1 if it timed out.