Principles of Task Division in Embedded Application Software
2026-04-06 07:22:27··#1
Introduction In the design of microcontroller application software based on a Real-Time Operating System (RTOS), "task" is a crucial concept. Experts point out that dividing an application system into tasks and defining the responsibilities of each task is an art. There are no universally accepted rules for task division; different people designing a system with the same specifications will have different solutions. However, to date, it is difficult to find papers that provide a detailed and systematic introduction to task division methods. This paper will delve into task division methods and, based on this, provide practical guidelines for writing application software based on the RTX51 Tiny real-time operating system. 1. The Concept of Tasks and the Application Software Development Process In the development of embedded real-time multi-tasking systems, a task, represented in C language code, is an infinite loop program. A task cannot return or exit, but it can be killed, including by other tasks or by self-destruction. The concept of a task is the same as the concept of a process in an operating system; a task is an independent execution process that can compete for CPU time with other concurrent tasks. The development process of microcontroller application software based on RTOS: First, the functions of the application software are clarified according to the system design scheme. Then, combined with the concurrency characteristics (or quasi-concurrency characteristics) of RTOS, the functions to be implemented by the application software are appropriately divided, that is, the functions of the application software are divided into several task modules according to certain principles, and the communication and latency between each task are carefully confirmed. 2. Principles of Task Division There are three principles of task division, which are introduced below. 2.1 Principle 1 Principle 1 is to place the access to the same peripheral device in one task. The driver segment that operates on each independent hardware (such as a serial communication port) is placed in one task. That is, to operate on a certain device resource, it is only possible to do so by executing the corresponding task. In this way, no matter when the task is switched, it will not affect any independent "peripheral". This avoids the special problems of embedded operating systems—resource conflicts and reentrancy problems, and is conducive to system maintenance and upgrades. Communication between tasks can be achieved by calling the os_send_signal function and global variables. The term "resource conflict" refers to a situation where task A accesses a resource, and a task switch occurs—switching from task A to task B. Task B also accesses the resource and changes its state. When task A is executed again, this can lead to conflicts or introduce uncertainty. "Reentrancy" refers to a situation where, assuming task A is running a function, a task switch occurs, and task B also runs the same function. This disrupts the execution context of task A, potentially leading to incorrect results. This problem is particularly prevalent in the operation of serial interface devices, such as serial ports, serial A/D, and D/A devices. 2.2 Principle 2 Principle 2 aims to improve system real-time performance through task partitioning. In embedded multi-tasking real-time systems, a task refers to a program segment. This program segment is scheduled by the operating system as a basic unit. Typically, each task is an infinite loop. An RTOS is essentially an embedded real-time kernel responsible for managing tasks, allocating CPU time to each task, and handling communication between tasks. Real-time kernels can be divided into preemptive and non-preemptive types. Therefore, based on the kernel used, embedded real-time systems can be divided into two categories: embedded real-time systems using non-preemptive kernels and embedded real-time systems using preemptive kernels. 2.2.1 Definition of Long Tasks In an RTOS, a long task refers to a task whose execution time is too long, exceeding the real-time tolerance of one or more other tasks in the RTOS, thus threatening the overall real-time performance of the RTOS. It is important to note that long tasks should not be confused with complex tasks; complex tasks do not necessarily have long execution times, and simple tasks can also constitute long tasks. 2.2.2 Impact of Long Tasks on RTOS When using a preemptive real-time kernel, long tasks, due to their longer execution time, are more easily interrupted by higher-priority tasks. Once a higher-priority task enters the ready state, the current task's CPU usage is preempted, or in other words, the task is suspended, and the higher-priority task immediately gains control of the CPU. This presents two problems: First, long tasks may be frequently interrupted during execution, resulting in prolonged periods without a complete execution. Second, when a long task is interrupted, a large amount of context information may need to be saved to ensure that the long task can continue execution after higher-priority tasks have finished and returned. However, this consumes system resources, and saving the context itself also consumes CPU time, thus reducing real-time performance. When using a non-preemptive real-time kernel, the impact of long tasks on the RTOS is even more pronounced because in this kernel, the response time of a task depends on the execution time of the longest task. In other words, due to the existence of long tasks, the response time of tasks increases. As a result, the CPU remains occupied by long tasks for extended periods, preventing other tasks from receiving real-time responses or even executing at all, inevitably leading to a decrease in system real-time performance. In short, regardless of whether a preemptive or non-preemptive kernel is used, long tasks pose a serious threat to the RTOS. 2.2.3 Solutions to the Long Task Problem The most effective way to solve the long task problem is through task partitioning. "Task partitioning" refers to dividing a long task that affects system real-time performance into several smaller tasks. In this way, the execution time of a single task is shortened, the task response time of the system is shortened, and the real-time performance is improved. (1) Analysis and calculation of tasks Of course, the division of long tasks must be combined with the kernel used in the system and the real-time requirements of each task, and necessary analysis and calculation must be carried out to ensure the rationality and effectiveness of the division. The specific steps are as follows: ① Analyze how many tasks there are in the system, how high the real-time requirements of these tasks are, and find the minimum execution frequency (f1, f2, ..., fn) required by each task. ② Calculate the actual execution time (t1, t2, ..., tn) of each task. ③ Determine the long tasks in the system. If max(t1, t2, ..., tn) ≤ min(1/f1, 1/f2, ..., 1/fn), then there are no long tasks in this system. If max(t1, t2, ..., tn) > min(1/f1, 1/f2, ..., 1/fn), then there is a long task, and the task with an execution time of max(t1, t2, ..., tn) is the long task we are looking for. ④ Analyze whether this long task needs to be split, analyze what causes the execution time to be too long, and whether this time can be shortened through program optimization? If so, then task splitting is not necessary; otherwise, this long task needs to be split. (2) The following are two common methods for implementing long task splitting: ① Divide the long task into several small modules according to its function. Each module constitutes a small task. Each small task implements a relatively independent function and ensures that the execution time t 3 Application Software Design Guidelines Based on RTX51 Tiny RTX51 is a multi-tasking real-time operating system developed by Keil Software in Germany for the 8051 series of microcontrollers. There are two different versions of RTX51. (1) Full RTX51 Full Full RTX51 Full allows for time-slice round-robin scheduling of tasks with four priorities and preemptive task switching. It can utilize interrupt functions in parallel. Signals and messages can be passed between tasks through the mailbox system. Memory can be allocated and released from a memory pool. A task can be forced to wait for interrupts, timeouts, and signals or messages from another task or interrupt. (2) Tiny Tiny Tiny Tiny is a subset of RTX51 that can easily run on a single-chip 8051 system without any external memory. RTX51 Tiny only supports time-slice round-robin task switching and task switching using signals; it does not support preemptive task switching. It can utilize interrupt functionality in parallel, and can force a task to wait for interrupts, timeouts, and signals from another task or interrupt. It cannot perform information processing and does not support memory allocation or deallocation. RTX51 Tiny is a non-preemptive real-time operating system kernel. When designing microcontroller application software based on the RTX51 Tiny real-time operating system, the first step should be to appropriately divide the functions to be implemented by the application software according to the quasi-concurrency characteristics of the RTX51 Tiny operating system—dividing them into several task modules according to the three principles mentioned above, and carefully verifying the communication and latency between each task. The guidelines for writing application software based on RTX51 Tiny are as follows: ① Include the header file rtx51tny.h in the application. ② Do not write a C language main function main(). The RTX51 Tiny operating system kernel already has its own main function main(). ③ The application should include at least one task function. ④ RTX51 Tiny applications must have interrupts enabled (EA=1) because the RTX51 Tiny operating system uses timer T0 interrupts. ⑤ The application must call at least one RTX51 Tiny system function (such as os_wait); otherwise, the linker will not include the RTX51 Tiny system libraries in the application. ⑥ Task 0 is the first function executed in the application. In task 0, the os_create_task function must be called to run other tasks. ⑦ Task functions do not need to exit or return. Tasks must use a while(1) structure or other similar structure. Task functions take no parameters and have no return value. Use the system function os_delete_task to suspend a running task. ⑧ Interrupt service routines are written in the same way as when not using the RTX51 Tiny operating system. ⑨ There are two ways to compile and link applications: one is to use the integrated development environment μVision 2 IDE, and the other is to use the command-line tools. The μVision 2 IDE, an integrated development environment (IDE) provided by Keil Software in Germany, is generally used. The initial steps for creating an RTX51 Tiny application using the μVision 2 IDE are as follows: ① Run the μVision 2 IDE. ② Run the menu command Project→Options for Target 'Target 1' to open the Target dialog box, and select the Target tab. ③ Select RTX-51 Tiny from the Operating system drop-down list box, as shown in Figure 1. 4. Conclusion This paper presents three principles for task partitioning: "Place access to the same peripheral device in one task," "Improve system real-time performance through task partitioning," and "Apply the 'decoupling principle' from software engineering to task partitioning." Practice has proven that these task partitioning principles are effective. Furthermore, from a practical perspective, guidelines for writing application software based on the RTX51 Tiny real-time operating system are provided. In fact, the hardware requirements of the RTX51 Tiny real-time operating system are very low. With the development of semiconductor technology, microcontroller chips that can run embedded real-time operating systems are easy to purchase. People are increasingly aware of the necessity of introducing a real-time operating system in embedded system design [5]. In many embedded systems, not only is it required that the system be able to respond to random external events in a timely manner and process them quickly, but it is also usually required to execute multiple tasks simultaneously and respond to each task in real time. Practice has proven that for such applications, using an embedded real-time operating system as the design platform and running platform for application software is a good choice.