Polling UART receive while having multiple tasks

Hello!

I am currently designing a system that is running FreeRTOS on a PIC24FJ128GU406.
This system has 3 tasks that have the same priority and run with a time slice of 1ms each.

I have a task that polls the data receive bit in the microcontroller and receive all incoming data from a UART while this receive bit is set.
The problem I am having is that I cannot receive a steam of multiple Bytes in a row as FreeRTOS is switching tasks in the middle of receiving (as expected).

Is there any way I can guarantee receiving all the incoming Bytes without losing any, WITHOUT having to use the UART receive interrupt?

Maybe by having FreeRTOS enter a crytical section, or something like that?

I am trying to desing an “interrupt free” system (appart from the FreeRTOS tick interrupt, of course).

Thanks in advanced for all input!
Luis

Why are you trying to be interrupt free? That is a fundamental property of RTOSes, that you stop “polling” for data, but block until data is there.

Fundamentally, your receive task might not get a time slice for a 2 ms period, and if more data then the UARTS fifo can arrive in that time, you will lose data.

Yes, a critical section could let you get all the data that was there without interruptions, but if you are looping waiting for the last character of a message in that section, you are delaying your other tasks.

Thanks Richard for your reply.

The reason to not use interrupts is because the system needs to be as predictable as possible.

If I did use an interrupt for this, as it’s probably the only-best option. Where do I create the interrupt handle? In a task?

Might be a simple question but it’s my first time using interrupts with FreeRTOS.

Thanks once again!

The UART RX interrupt handler is not created in a task. It is a standalone function provided at the MCU/peripheral level — part of your HAL (Hardware Abstraction Layer).

Interrupts are configured and enabled outside of tasks, usually at system init.
These interrupts signal tasks using various RTOS methods like semaphores, queues or task notifications.

Thank you Karahulx! :slight_smile:

The issue is that not using interrupts probably adds MORE unpredictability, as you will have a task polling for an unpredictable period.

Receiving serial data with an ISR, and putting it into a buffer won’t have must time used. If you have a short interval where even that sort of delay is unacceptable, THAT should be in a critical section (if it can’t be done in a higher priority interrupt).

To ensure that all incoming UART bytes are received without interruption, without using interrupts, you can leverage critical sections in FreeRTOS. By temporarily disabling task switching (using taskENTER_CRITICAL() and taskEXIT_CRITICAL()), you can prevent FreeRTOS from switching tasks while you’re reading the UART data. This ensures that the task polling the UART can complete the data reception without being preempted. However, keep in mind that this approach could lead to longer critical sections if the data stream is long, so you need to balance this with the overall responsiveness of the system. Another alternative is to adjust the task priorities, giving the UART task a higher priority, although that would still involve task switching and could impact other tasks.

I wonder whether the official demo configure the UART receive mode such as mps2-an385 and lm3s6965. If not, what can I to set them? Because there are many .c/.h files in the demo folder and many indirectly referenced functions (declarations can only be found in .h file, but the .c file containing it is hard to found).
For example, when I try to change main-blinky.c to use getchar() receiving strings from terminal and doesn’t change any other configuration in main.c in mps2-an385 QEMU demo, the QEMU terminal showes some errors like
qemu: fatal: Lockup: can’t escalate 3 to HardFault (current priority -1)
Calling prvGetRegistersFromStack() from fault handler