Can Microcontrollers Truly Execute Multiple Tasks Simultaneously?

Many students ask me: Why does my LED light blink while the serial port data reception gets stuck? I want to read data from two sensors simultaneously, why is it that one of them always reads incorrectly? Why can’t my program control the motor while sending data? The most classic question is: why can’t I receive data from two serial ports at the same time?

These questions point to a core issue: Can microcontrollers really execute multiple tasks simultaneously?

1.A single core can only do one thing at a time.

The brain of a microcontroller is like a person, no matter how capable this person is, they can only execute one instruction at a time, only do one thing. It is impossible to execute the instruction to read from serial portA and the instruction to read from serial portB at the same nanosecond. It is impossible to execute two pieces of code simultaneously.

2. So why does it seem like many things can be done at once?

Why can my phone play music, chat on WeChat, and download something at the same time? Can a microcontroller also make lights blink, receive data from the serial port, and turn motors? Can it achieve such effects? The answer is: yes! But not through true simultaneity.

Microcontrollers switch between different tasks very quickly, creating an illusion of simultaneous operation. Just like a person: quickly checking if there is data on serial portA, then immediately turning to check if there is data on serial portB. Then quickly checking the timer to see if the LED should blink. Then back to serial portA to check again, and this continues in a loop. If the switching is fast enough, at the millisecond or microsecond level, to our eyes, the light is blinking, serial portA is receiving, and serial portB is also receiving, making it seem like everything is happening simultaneously. It appears simultaneous, but in reality, it is rapid alternating execution, which is concurrency.

3. Main methods of concurrency

1. Super loop + polling:

This is done in a large while(1) infinite loop, arranging the order yourself:

Can Microcontrollers Truly Execute Multiple Tasks Simultaneously?

Simple and intuitive, with very low resource consumption, suitable for resource-limited 8-bit and 16-bit microcontrollers.

The downside is that everything has to be scheduled manually. If processing data from serial portA is particularly time-consuming, then subsequent tasks like serial portB, LED, and buttons have to wait, which is why sometimes one task can block others. Careful design is needed to avoid time-consuming operations blocking the loop. It’s like a waiter being held up by one table of customers, leaving the other tables unattended.

2. Interrupts:

Polling has a drawback, the CPU has to actively ask each device “Do you have anything?” This can be inefficient, especially when devices are not frequently active. That’s where interrupts come in. Interrupts allow external events to interrupt the code currently being executed by the CPU, providing almost real-time response. Interrupts + polling is a particularly efficient way for bare-metal programs to handle multitasking. The main loop handles primary logic and less urgent tasks, while interrupts handle urgent events.

3. Real-Time Operating System (RTOS):

When tasks become numerous and complex, scheduling them manually becomes too laborious and error-prone. At this point, a manager is needed, the RTOS, to manage multiple tasks. It is responsible for automatically and quickly switching between these tasks in the background. When one task needs to wait, the manager immediately hands over the CPU to other ready tasks.

Task switching is faster and fairer, and one task blocking will not freeze the entire system. It simplifies programming, making it more like describing what each independent task should do, while scheduling is handled by the RTOS. It also facilitates the use of interrupts; once an interrupt is handled, it can wake up tasks waiting for events.

The downside is that it requires additional memory and CPU resources to run the RTOS, increasing complexity. It requires a slightly more powerful 32-bit microcontroller.

The key is, even under an RTOS, a single CPU still executes only one task’s code at a time, the RTOS just makes switching more efficient and reasonable.

4. So is it completely impossible to execute multiple pieces of code simultaneously?

Are there microcontrollers that can truly execute tasks simultaneously? Yes! In parallel: truly doing multiple things at once means multi-core microcontrollers.

These microcontrollers integrate two or more independent CPU cores. They can genuinely assign different tasks to run simultaneously on different cores. CoreA focuses on processing data from serial portA, while coreB processes data from serial portB simultaneously, without interference.

Examples include ESP32, Raspberry Pi RP2040, NXP’s i.MX RT series, and higher-end application processors, such as the multi-core chips in the Raspberry Pi’s Cortex-A series.

The downsides are higher costs, greater power consumption, and more complex software, requiring stronger development capabilities.

So for single-core microcontrollers: one person, relying on speed, quickly switches to pretend to do many things at once. For multi-core microcontrollers: multiple people, truly working together to do many things at once. Understanding this essence allows us to use polling, interrupts, RTOS and other methods to make microcontrollers multitask effectively!

Leave a Comment