Abstract This paper introduces the concept and characteristics of the embedded real-time operating system, and briefly describes the core structure of the embedded operating system μC / OS-II.
Key words embedded real-time operating system, μC / OS-II, interrupt, task, priority
1 Embedded real-time operating system overview [1]
The so-called embedded system is based on application, based on computer technology, software and hardware can be cut, which can adapt to a special computer system for functional, reliability, cost, volume, power consumption, etc. in practical applications. It is generally composed of four parts of the embedded microprocessor, peripheral hardware device, embedded operating system, and user application software to implement control, monitoring, or management of other devices. In large embedded applications, in order to make embedded development more convenient, fast, there is a set of stable, secure software module sets to manage memory allocation, interrupt processing, inter-task communication and timer response, and provide more Task handling, etc., that is, an embedded operating system. The introduction of the embedded operating system greatly enhances the function of the embedded system, which is convenient for the design of the application, but also occupies valuable embedded system resources. Embedded operating systems often have real-time requirements, so embedded operating systems are often "real-time operating systems". Early embedded systems are almost all of them for control purposes, thereby more or less real-time requirements, so the "embedded operating system" is actually synonymous with "real-time operating system". In recent years, there have been many embedded operating systems without real-time requirements due to the emergence of handheld computers and handheld computers. On the other hand, since the CPU speed is improved, some reaction speeds that are originally "real-time" are now very common. In this way, some applications that need to be implemented in the "real-time" operating system are now not difficult to implement on the regular operating system. In this context, "embedded operating system" and "real-time operating system" have become different concepts and nouns. The real-time operating system can promptly respond to the request of the external event, and complete the processing of the event in the specified time, and control all real-time tasks and coordinated operations, with independence, timely, and reliability. As the name suggestion, the embedded real-time operating system is formed after the characteristics of the above two operating systems, the embedded real-time operating system does not have a general content of the computer operating system file management, and there is generally no memory management, it It has the most important content in real-time operating systems, namely, scheduled, synchronous operations. The size of its binary code is usually a few KB to dozens of KB, which is designed to be embedded, with a short task switching time and a high real-time response speed. The core of the embedded real-time operating system is a real-time multi-tasking kernel.
2 Introduction to Embedded Real-Time Operating System μC / OS-II [2]
μC / OS-II is a real-time kernel of the famous source code, is a complete, portable, curing, cropping of a priority real-time multi-tasking core. μC / OS-II is written in ANSI C, including a small part of the assembly language code related to the microprocessor type, so that the microprocessor of different architectures can be used. Although μC / OS-II is developed and tested on the PC, the actual object of μC / OS-II is an embedded system, and it is easily ported to the microprocessor of different architectures. So far, from 8 to 64-bit, μC / OS-II has run on a microprocessor of different architectures in 40.
3 Embedded real-time operating system μC / OS-II core structure
3.1 critical sections, os_enter_critical () and OS_EXIT_CRITICAL ()
Like other core, μC / OS-II must be interrupted in order to handle the critical area code, and then open the interrupt after processing. The interrupt makes μC / OS-II to avoid other tasks or interrupt services to enter the critical zone code. The time of the interruption is one of the most important indicators that real-time kernel developers, as this indicator affects the response characteristics of the user system on real-time events. The μC / OS-II effort makes the shuttle time to the shortest, but in turn use μC / OS-II, the time off the interrupt depends to a large extent on the structure of the microprocessor and the code quality generated by the C compiler. . Microprocessors generally have interrupt and open interrupt instructions, and the C compiler used by the user must have some mechanism, and it is possible to directly implement off / open interrupt operations in C source code. Some C compilers allow the statement to embed the assembly language in the user's C source code, so that the off interrupt / open interrupt is easy to implement; and some C compilers put the operation from the C language interrupt / open interrupt in the language extension Part, thereby directly interrupt / open interrupt from the C language.
μC / OS-II defines two macros to interrupts and interrupts to avoid different methods of using different methods to handle closing interrupts and open interrupts. These two macros in μC / OS-II are OS_Enter_critical () and OS_EXIT_CRITICAL (). Because the definition of these two macros depends on the microprocessor used, the corresponding macro definition can be found in the file os_cpu.h. Every microprocessor has its own os_cpu.h file.
OS_ENTER_CRITICAL () and OS_EXIT_CRITICAL () are always used, and the critical zone code is encapsulated, as shown in the following code:
{
......
......
OS_ENTER_CRITICAL ();
/ * μC / OS-II critical zone code * /
OS_EXIT_CRITICAL ();
......
......
}
OS_ENTER_CRITICAL () and OS_EXIT_CRITICAL () can also be used to protect critical area code in the application.
3.2 Task (Tasks)
The task is usually an infinite loop, but when the task is completed, the task can be self-deleted. μC / OS-II can manage up to 64 tasks, but the author of μC / OS-II recommends that users do not use the tasks of priority 0, 1, 2, and 3, and the priority is OS_LOWEST_PRIO-3, OS_LOWEST_PRIO-2, OS_LOWEST_PRIO-1 and OS_LOWEST_PRIO tasks, because these tasks may be used in the future μC / OS-II versions. Therefore, if you follow the author's recommendations, you don't use 4 tasks and 4 tasks with the highest priority of the priority, you can have up to 56 yourself.
3.3 Task Status (Task State)
The following figure is a task status conversion map under μC / OS-II control [3]. At any given moment, the state of the task should be one of the following five states.
Sleep (Dormant) means that the task resides in the program space, has not been handed over to μC / OS-II. Give the task to μC / OS-II, which is implemented by calling one of the following two functions: ostaskcreate () or ostaskcreateext (). These calls are just used to tell μC / OS-II, where is the starting address of the task, when the task is established, how much the priority given to the task; how many stack spaces are to be used.
On the Ready - Task Once established, this task enters the read state, ready to run. The establishment of the task can be established by a running task before the multi-task run is started. If the multitasking has been started, and a task is established by another task, and the new task priority is higher than the priority of establishing its task, the just established task will immediately get the right of the CPU. One task can return to sleep state by calling ostaskdel () or by calling the function to enter the sleep state. Running - Call OSStart () You can start multiple tasks. The OSStart () function can only call once at startup, the function runs the user's initialization code, and enters the highest priority task. The highest priority task has entered the operation state. Only one task can be run at any time. Ready tasks Only when all priority is higher than this task, or deleted it, you can enter the run state.
Waiting State (Waiting) - The task is running can be delayed by calling one of the following two functions: ostimedly () or ostimedlyhmsm (). This task then enters the waiting state, until the delay time defined in the function. These two functions will immediately enforce task to switch, so that the next priority is the highest priority, and enters the task running on the read state. After waiting for the time, the system service function OSTIMETICK () makes the latency task into the read state. And running tasks may need to wait for an event, you can implement one of the following functions: Osflagpend (), OSSEMPEND (), OSMuteExpend (), OSMBoxpend () or OSQPEND (). If the event does not happen, the task that calls the above function has entered the waiting state until the waiting event occurs. When the task is suspended by the event, the next priority task immediately got the right to use the CPU. When the event occurs or waiting for timeout, the pending task enters the read state. The incident report may come from another task or from the interrupt service subroutine.
Interrupt Service (ISR) - The task that is running is to be interrupted unless the task will be interrupted, or the μC / OS-II will be interrupted. The task being interrupted has since entered an interrupt service state. When the corresponding interruption, the task being executed is suspended, and the interrupt service subroutine has obtained the right to use the CPU. The interrupt service subroutine may report the occurrence of one or more events to enable one or more tasks. In this case, the μC / OS-II determines whether the task of the interrupted task is highest in the read state task before returning from the interrupt service subroutine. If the interrupt service subroutine enters the other priority task to encompasses, the new entry will be a higher priority task to run; otherwise, it will continue to operate by a lot of tasks.
When all tasks are waiting for the end of the event or the end of the delay time, the μC / OS-II executes the internal task known as idle task, ie OSTASKIdle ().
3.4 Task Control Block (Task Control Blocks)
Once the task is established, a task control block OS_TCB is assigned. Task Control Block is a data structure that is deprived when the task's CPU usage is deprived, and the μC / OS-II uses it to save the task. When the task reaches the CPU usage, the task control block ensures that the task continues from the point that is interrupted at the time. OS_TCB is all resident in the RAM.
3.5 Ready List
Each task is given a different priority level, from 0 to the lowest priority OS_LOWEST_PRIO, including 0 and OS_LOWEST_PRIO. When μC / OS-II is initialized, the lowest priority OS_LOWEST_PRIO is always assigned to idle tasks. Each ready task is placed in the ready table, and there are 2 variables in the ready table, OSRDYGRP and OSRDYTBL []. In OSRDYGRP, the task is packetized by priority, and 8 tasks are a group. Each of OSRDYGRP represents the task that has entered the read state in the 8 sets of tasks. When the task enters the readable state, the corresponding elements of the corresponding elements in OSRDYTBL [] are also set to 1. The relationship between osrdygrp and osrdytbl [] is shown below [3]:
The STY OSRDYTBL [] The size of the array depends on OS_LOWEST_PRIO. When the number of tasks in the application is relatively small, this arrangement can reduce the value of OS_LOWEST_PRIO, which can reduce the demand for μC / OS-II to RAM.
To determine which priority task is running, the scheduler in the μC / OS-II always closes the lowest priority task in the respective byte of the corresponding byte 1.
As can be seen from the above figure, the low 3 bit of task priority is used to determine the task in the OSRDYTBL [] of the task. The next three digits are used to determine the first element in the OSRDYTBL [] array.
3.5 Task Scheduling
μC / OS-II always runs to enter the task of the highest priority in the read state task. Determine which task priority is the highest, which task should be run, this work is done by the scheduler (Scheduler). The schedule of task-level is done by the function os_sched (). The scheduling of the interrupt level is done by another function osortext (). The execution time of the μC / OS-II task scheduling is constant, which has no relationship with how many tasks have been established.
Task Switch is simple, completed by step 2: Press the processor register of the suspended task into the stack; then returns the register value of higher priority tasks from the stack to the register. In μC / OS-II, the stack structure of the ready task always seems to have just happened, all processors' registers are saved in the stack. In other words, all the tasks that the μC / OS-II runs on the read state, just restore all CPU registers and run the interrupt return instruction. In order to make a task switch, run OS_TASK_SW (), and people imitate one interrupt. Most microprocessors implements the above operations by a soft interrupt command or an instruction trap. Interrupt service subroutine or trap processing, also known as an abnormality, must provide an interrupt vector to assemble language functions osctXsw (). OsctXsw () In addition to the need to point to OS_TCBHighrdy points to the upcoming task, you also need to let the current task control block OSTCBCur point to the upcoming task.
All code of OS_SCHED () belongs to the critical area code. During the task process of finding the highest priority of the read state, to prevent the interrupt service subroutine from putting one or several tasks, the interrupt is closed. In order to shorten the switching time, all code can be written in assembly language in the os_sched (). In order to increase readability, portability, and assemble the assembly language code, OS_sched () is written in C language.
3.6 Lock and unlock the scheduler (Locking and Unlocking the scheduler)
To the scheduler upper lock function OSSChedLock () is used to disable task scheduling until the task is completed, call to the scheduler unlock function OsSchedunlock (). The task calling OsSchedlock () will remain the right to use the CPU, even if there is a higher priority task enters the read state. At this time, the interrupt is still identifiable, the interrupt service can also be obtained (assuming that the interrupt is open). OsSchedlock () and OSSCHEDUNLOCK () must be used. Variable OSLockNesting Tracking OsSchedlock () Functions The number of times to allow nested functions to include critical zone code, this code other tasks must be intervened. μC / OS-II allows the nesting depth to 255 floors. When oslocknesting = 0, the task scheduling is re-enabled. The use of OsSchedLock () and OsSchedunlock () is very cautious because they affect the normal management of μC / OS-II to tasks. After calling OsSchedlock (), the user application may not call the system function function that may cause the current task. That is, the user application may not call OSFlagpend (), OSMBoxpend (), OSMuteExpend (), OSQPEND (), OSSemPend (), OSTASKSUSPEND (OS_PRIO_SELF), OSTIMEDLY () or OSTIMEDLYHMSM () until oslocknesting back 0. Because OsSchedLock () is locked on the scheduler, the user locked the system without letting other tasks. 3.7 Idle Task (IDLE Task)
μC / OS-II always establishes an idle task that is ready to be put into operation without other tasks. This idle task (ostaskidle ()) is always set to the lowest priority, ie os_lowest_prio. Idle tasks cannot be deleted by the application.
3.8 Statistics Task (Statistics Task)
μC / OS-II has a statistical runtime task called ostaskstat (). If you set the system configuration constant os_task_stat_en to 1, this task will be established. Once allowed, Ostaskstat () runs once a second, calculates the current CPU utilization. In other words, ostaskstat () tells the user that how much CPU time is used, with a percentage. This value is placed in a symbol 8-bit integer oscpuusage, accuracy is 1%. If the application is intended to use the statistical task, you must establish a unique task to create the statistical task initialization function osstatinit () during initialization. In other words, a task must be established in the user initial code before calling the system start function OSSTART (), and the system statistics task initialization function osstatinit () is called in this task, and then the other tasks in the application are set.
Interrupt in 3.9 μC / OS-II (Interrupts under μC / OS-II)
In μC / OS-II, the interrupt service subroutine should be written in assembly language. However, if the C language compiler used by the user supports an online assembly language, you can directly place the interrupt service subroutine code in the source file of the C language. The interrupt service process of μC / OS-II is approximately as follows:
1) Interrupt arrival, but it is not recognized by the CPU. Perhaps because the interrupt is passed by μC / OS-II or user application, or because the CPU has not yet been executed.
2) Once the CPU responds to this interrupt, the CPU's interrupt vector is loaded, jumps to the interrupt service subroutine. 3) The interrupt service subroutine saves all registers of the CPU.
4) After saving the CPU register, the interrupt service subroutine notifies the μC / OS-II to enter the interrupt service subroutine. The practice is to call Osintenter (), or give the OsintneSting home 1. Stack pointers should also be saved to the current task control block OS_TCB.
5) User Interrupt Service Code begins to execute. The interruption of the service should be as small as possible, and most of the work should be left to the task.
6) After the interrupt service is complete, you must call Osintexit (), and notify μC / OS-II to exit the interrupt service.
7) Restore the register of the CPU and the interrupt is returned.
3.10 Clock Tiantai (Clock Tick)
The μC / OS-II needs to provide a periodic signal source for time delay and confirmation timeout. The race rate should be 10 ~ 20 times / second, or 10 ~ 100 Hz. The higher the clock tap rate, the heavier the additional load of the system. The actual frequency of clock beats depends on the accuracy of the application. The clock source can be a special hardware timer or a signal from a 50 / 60Hz AC power source. After the multi-task system is started, it is also to turn on the clock beam after calling OsStart (). In other words, the first thing to do after call OsStart () is to initialize the timer interrupt. Usually the error that is easily made is that the clock beam is allowed to be in the system initialization function Osinit (), before starting the multi-tasking system start function OSStart (). The clock beat service in μC / OS-II is to be implemented by calling OSTIMETICK () in the interrupt service subroutine. Ostimetick () Tracks the timers of all tasks and timeouts, the code of the clock-taking interrupt service subroutine must be written in assembly language because the CPU registers cannot be directly processed in the C language.
3.11 μC / OS-II initialization (μC / OS-II Initialization)
The μC / OS-II requires the system initialization function osinit () before calling the μC / OS-II. Osinit () initializes all variables and data structures of μC / OS-II. Osinit () establishes free task ostaskidle (), this task is always ready. The priority of idle task ostaskidle () is always set to the lowest, osp_lowest_prio. If the statistical task allows OS_TASK_STAT_EN and task establishment extensions to be set to 1, OSINIT () also requires statistical task os_taskstat (), and makes it ready. The priority of OS_TASKSTAT is always set to OS_LOWEST_PRIO-1.
3.12 μC / OS-II start (Starting μC / OS-II)
The launch of multiple tasks is implemented by calling OsStart (). However, at least one application task must be established before starting μC / OS-II. When the OSStart () is called, OSStart () finds the task control block of the user's highest priority task from the task schedule. Next, OSStart () calls the high priority ready task start function OSSTARTHRDY () function, the latter returns the value saved in the task stack back into the CPU register, and then executes an interrupt return command, the interrupt return instruction enforces the task code.
4 Conclusion
The above-described core structure of the embedded real-time operating system μC / OS-II is briefly introduced, it can be seen that the basic functions and good portability of the μC / OS-II have a embedded real-time operating system kernel, which is already The embedded system has been widely used.
references
[1] Ma Zhongmei Li Shanping Kang Joint Nan, "ARM & Linux Embedded System Tutorial", Beijing University of Aeronautics and Astronautics Press, 2004 [2] Jean J. Labrosse, Shao Beibei and other translations, "embedded real-time operating system μC / OS-II (2nd Edition) ", Beijing University of Aeronautics and Astronate University Press, 2003
[3] Jean J. Labrosse, "Microc / OS-II THE Real-Time Kernel Second Edition", CMP Books, 2002
A brief introduction to Embedded RTOS kernel μC / OS-II
Abstract
.
Keywords
Embedded RTOS, μC / OS-II, Interrupt, Task, Priority