Http://blog.csdn.net/fyh2003/article/details/6176393
Rex is an operating system developed by Qualcomm. It was initially developed for applications on the Inter 80186 processor and then converted into applications on the ARM microprocessor. He has gone through many versions, more and more code, and more functions. Rex only uses less than 5 kb of Rom storage space. In the past, the compilation code and C code of the Rex system combined more than one thousand lines, but now there are more than fifteen thousand lines. In addition to the support of high-performance hardware, the improvement of functions requires more reasonable system design.
As a real-time embedded operating system, Rex has several notable features: simple, efficient, preemptible, multitasking, and real-time.
We can all understand that the embedded operating system has such common characteristics that it does not provide a variety of functions like a large operating system, it only needs to provide some corresponding functions according to the basic needs of the mobile phone, and as an embedded operating system, it must have a small power consumption, in this way, the cell phone can be properly controlled in terms of its shape and size. It is also suitable for battery-powered devices such as mobile phones. Efficient: the real-time system does not evaluate the efficiency based on the number of operations per second, but on the response time and duration of an event. Rex is a real-time system that requires fast event response. It cannot be said that the user has pressed a key and the system has not waited for a few minutes. The REX system not only responds quickly, but also processes Events quickly. The REX system is multi-task. In our sense, Rex can execute multiple tasks at the same time, which also reflects the efficient features, but in fact it is the same as other operating systems, it is also based on the rapid rotation of the CPU in different tasks to achieve the form of multi-task. In this way, a problem occurs: How does one rotate multiple tasks between CPUs? In this way, another feature of Rex is used: preemptible. Rex is preemptible. Once a task with the highest priority is ready, it can always get control of the CPU, that is, it can seize the CPU of a running task. In the previous Rex system, each task has a different priority. It is always clear to compare which task in the ready state will obtain the CPU, but in the later REX version, to allow different tasks to have the same priority, another scheduling method is required, that is, to schedule tasks with the same priority by time slice.
In the previous article, we are discussing the scheduling between multiple tasks. What is a task? In an embedded real-time operating system, a task is equivalent to a thread. There are many tasks in Rex. We can understand the functional modules running in Chengdu. Each task has its own stack, runtime space, signal, queue, and so on. They are independent and do not interfere with each other. Each task implements a relatively independent function. However, each task must have its own stack, which requires that there should not be too many tasks in Rex.
Browser is run in Rex as a task because it occupies too many resources, but then it is put into brew. We should note that we cannot add new tasks as a last resort. The REX operating system will first create an idle task and main task, and then use main task to control the creation of other tasks. The main task is mc_task. After it is created, it will first create some important services such as clock, data service, Database Service, encoder driver, RF driver, etc, then define and create some tasks. First, define the sleep task, then the dog task, and then other tasks, I have been confused about the memory copy, definition, and service start sequence of these tasks. Considering Rex's strict and careful priority system, the seemingly chaotic definition order of these tasks certainly makes sense, although I am still confused about it, however, static creation of mc_task and dynamic creation of other tasks by mc_task are implemented. Rex uses the rex_def_task () function to define a task. This function is structured into a stack, and a TCB is created to correspond to the task, and then the task is placed in the task.
List. Each task has its own TCB, that is, the task control block of the task. TCB contains the stack address, task entry, and task priority (priority) of the task ), task signal and other information related to the task. Rex allows the user to directly operate the TCB structure. After the tasks are defined and initialized, they are not run immediately, but executed successively based on their priorities. The tasks with the highest priority start to run after they are ready, the priority is determined based on the logical relationship between software and hardware and the importance and frequency of the task, therefore, this preemptive approach also reflects the efficient features while balancing fairness. In the program, these are the best
The concepts of task and current task are as follows:
Rex_set_best_task (rex_task_list_front ());
This is the concept of scheduler, that is, scheduling. It is implemented as a function in Rex: rex_sched (). It cannot be directly called by the app. Before calling rex_sched (), you must set the global variable rex_best_task. Its basic algorithm can be represented by the following pseudo code:
The current task pressure stack is saved. Wait until it pops up again.
Tasks need to communicate with each other, and the communication between tasks is much more difficult than that between apps. This is also the reason why the web browser changed from task to app. Tasks communicate with each other by semaphores, and the tasks are switched over by clearing and waiting through semaphores.
Typically, when a mc_task creates a task, it first defines a task, initializes the data required by the task, and then waits for the MC to execute the task with the highest priority in the ready state, wait until the task Initialization is complete and the preparation starts. Then return a feedback signal to MC. Note that the feedback signal here does not matter which signal is sent, that is to say, if a task is ready, MC will be returned. After that, the task waits for an infinite loop signal. This signal can be a cmd signal, a timer signal, or a start signal. After receiving the signal, the task processes the signal according to the signal. In this way, different signals can be used to control the running of tasks.
In Rex, these signals are stored in the TCB of the task, and the semaphores are a flag bit. Each signal is a 1-bit binary number, in the 32-bit arm, there are a maximum of 32 semaphores. Each semaphore represents a different meaning. Tasks can customize semaphores. You can use the rex_wait () function to wait for a signal and suspend yourself. Tasks can only be suspended in this way, for other tasks or interruptions, you can use rex_get_sigs (), rex_set_sigs (), rex_clr_sigs () to perform signal operations on a task. When task
When a signal is set to Task B, the task also stores some data in a specific buffer. If a signal is set, task scheduling is triggered, task B receives this signal and is in the ready state. Once Task B has a high priority enough to run, Task B can read data from the buffer, thus realizing communication between tasks. The signal is stored in the task's own TCB, thus realizing the purpose and security of signal transmission.
Rex also provides the timer function. There are two types of Timer: clock timer and custom timer. When clk_timer arrives, it calls back the call back function and immediately executes the desired operation. The custom timer does not. It sets only one signal. If it is not executed, it depends on the priority of the task. Timer can be customized through rex_set_timer. Timer operations include rex_get_timer, rex_resume_timer, rex_cls_timer, rex_pause_timer, and rex_timed_wait.
Every tick of the system's clock will check whether the timer has arrived. Rex maintains a special list to store the timer. Once the timer expires, Rex will remove the timer from the list, but it is not deleted, only Rex does not know the existence of this timer. Timer can only be created and owned by tasks. Note that rex_set_timer cannot be called on an active timer. The cyclic timing detection of the program is based on the existence of timer, which enables the operating system to respond to events in discrete time in a timely manner.
When a timer arrives, or other signal settings may cause task scheduling, the concept of interruption must be mentioned in task scheduling. As the name suggests, an interrupt is to interrupt the current operation to perform other operations. The operating system will execute an interrupt at intervals to check whether the highest priority of the current ready-state task is the current task, or the task is interrupted spontaneously. That is, call rex_wait. Since the interruption will damage the running of the current task, but when a piece of code cannot be interrupted, it is necessary to execute the Guanzhong disconnection operation. This code is called the critical code segment. After executing this code segment, immediate interruption is also required. If task a voluntarily wait after the disconnection is executed, the disconnection will be stored without affecting the next task.
When a runs again, the disconnection status is restored. Pay attention to the following issues: 1. do not operate too much in the interrupted code; 2. do not use loops or wait for interruptions; 3. do not change the global variable when the task is interrupted, which may cause execution errors of the suspended task. 4. clk_tick_isr is also interrupted.
In the operating system, you must consider the issue of mutual exclusion and resource sharing. If both of them want to cross a river, but there is only one wooden Bridge on the River, if both of them occupy this bridge at the same time, neither of them can cross the river. This involves the concept of mutual exclusion. Rex provides the concept of critical section and mutual exclusion. In particular, we note that the critical code is disconnected to achieve mutual exclusion. In fact, the resource mutex between tasks can also be solved by semaphores. In this case, there is a problem: if there are three tasks, their priority order is as follows: task a> Task B> task C, task C runs first, it occupies the task
A's resources. At this time, task a is in the suspend State because it does not get the resources. In the process of running task C, Task B is ready, the system suspends task C during the interruption and runs Task B. In this way, the priority is reversed. The solution to this problem is to dynamically change the priority, that is, to increase the priority of task C. Rex supports a dynamic change of priority, but this can only be done after careful consideration, because the priority is strictly defined, and once changed, it may cause unpredictable consequences. The dynamic definition of priority is implemented through priority inheritance, that is, task C inherits the priority of task.
Rex has a strong storage zone protection function, which stores some important information in NV. Read Information from NV During task execution for the task. The hardware of the embedded operating system must be very small. Rex stores all static variables in a zone, and then the space required by each task, followed by the storage zone of dynamic variables, the size of the storage area should be implemented by the programmer, so that the programmer can reasonably arrange the size of the space used. Generally, the stack size of a task is determined. Therefore, a large array or struct cannot be used in the task, because the stack where the task is located will pop up.
If (rex_best_task = rex_curr_task)
Return;
Else if (the system is currently servicing interrupts)
{
Rex_curr_task = rex_best_task;
}
Rex_curr_task = rex_best_task;
Rex_start_task (rex_best_task );
Http://blog.csdn.net/fyh2003/article/details/6176393
Rex is an operating system developed by Qualcomm. It was initially developed for applications on the Inter 80186 processor and then converted into applications on the ARM microprocessor. He has gone through many versions, more and more code, and more functions. Rex only uses less than 5 kb of Rom storage space. In the past, the compilation code and C code of the Rex system combined more than one thousand lines, but now there are more than fifteen thousand lines. In addition to the support of high-performance hardware, the improvement of functions requires more reasonable system design.
As a real-time embedded operating system, Rex has several notable features: simple, efficient, preemptible, multitasking, and real-time.
We can all understand that the embedded operating system has such common characteristics that it does not provide a variety of functions like a large operating system, it only needs to provide some corresponding functions according to the basic needs of the mobile phone, and as an embedded operating system, it must have a small power consumption, in this way, the cell phone can be properly controlled in terms of its shape and size. It is also suitable for battery-powered devices such as mobile phones. Efficient: the real-time system does not evaluate the efficiency based on the number of operations per second, but on the response time and duration of an event. Rex is a real-time system that requires fast event response. It cannot be said that the user has pressed a key and the system has not waited for a few minutes. The REX system not only responds quickly, but also processes Events quickly. The REX system is multi-task. In our sense, Rex can execute multiple tasks at the same time, which also reflects the efficient features, but in fact it is the same as other operating systems, it is also based on the rapid rotation of the CPU in different tasks to achieve the form of multi-task. In this way, a problem occurs: How does one rotate multiple tasks between CPUs? In this way, another feature of Rex is used: preemptible. Rex is preemptible. Once a task with the highest priority is ready, it can always get control of the CPU, that is, it can seize the CPU of a running task. In the previous Rex system, each task has a different priority. It is always clear to compare which task in the ready state will obtain the CPU, but in the later REX version, to allow different tasks to have the same priority, another scheduling method is required, that is, to schedule tasks with the same priority by time slice.
In the previous article, we are discussing the scheduling between multiple tasks. What is a task? In an embedded real-time operating system, a task is equivalent to a thread. There are many tasks in Rex. We can understand the functional modules running in Chengdu. Each task has its own stack, runtime space, signal, queue, and so on. They are independent and do not interfere with each other. Each task implements a relatively independent function. However, each task must have its own stack, which requires that there should not be too many tasks in Rex.
Browser is run in Rex as a task because it occupies too many resources, but then it is put into brew. We should note that we cannot add new tasks as a last resort. The REX operating system will first create an idle task and main task, and then use main task to control the creation of other tasks. The main task is mc_task. After it is created, it will first create some important services such as clock, data service, Database Service, encoder driver, RF driver, etc, then define and create some tasks. First, define the sleep task, then the dog task, and then other tasks, I have been confused about the memory copy, definition, and service start sequence of these tasks. Considering Rex's strict and careful priority system, the seemingly chaotic definition order of these tasks certainly makes sense, although I am still confused about it, however, static creation of mc_task and dynamic creation of other tasks by mc_task are implemented. Rex uses the rex_def_task () function to define a task. This function is structured into a stack, and a TCB is created to correspond to the task, and then the task is placed in the task.
List. Each task has its own TCB, that is, the task control block of the task. TCB contains the stack address, task entry, and task priority (priority) of the task ), task signal and other information related to the task. Rex allows the user to directly operate the TCB structure. After the tasks are defined and initialized, they are not run immediately, but executed successively based on their priorities. The tasks with the highest priority start to run after they are ready, the priority is determined based on the logical relationship between software and hardware and the importance and frequency of the task, therefore, this preemptive approach also reflects the efficient features while balancing fairness. In the program, these are the best
The concepts of task and current task are as follows:
Rex_set_best_task (rex_task_list_front ());
This is the concept of scheduler, that is, scheduling. It is implemented as a function in Rex: rex_sched (). It cannot be directly called by the app. Before calling rex_sched (), you must set the global variable rex_best_task. Its basic algorithm can be represented by the following pseudo code:
The current task pressure stack is saved. Wait until it pops up again.
Tasks need to communicate with each other, and the communication between tasks is much more difficult than that between apps. This is also the reason why the web browser changed from task to app. Tasks communicate with each other by semaphores, and the tasks are switched over by clearing and waiting through semaphores.
Typically, when a mc_task creates a task, it first defines a task, initializes the data required by the task, and then waits for the MC to execute the task with the highest priority in the ready state, wait until the task Initialization is complete and the preparation starts. Then return a feedback signal to MC. Note that the feedback signal here does not matter which signal is sent, that is to say, if a task is ready, MC will be returned. After that, the task waits for an infinite loop signal. This signal can be a cmd signal, a timer signal, or a start signal. After receiving the signal, the task processes the signal according to the signal. In this way, different signals can be used to control the running of tasks.
In Rex, these signals are stored in the TCB of the task, and the semaphores are a flag bit. Each signal is a 1-bit binary number, in the 32-bit arm, there are a maximum of 32 semaphores. Each semaphore represents a different meaning. Tasks can customize semaphores. You can use the rex_wait () function to wait for a signal and suspend yourself. Tasks can only be suspended in this way, for other tasks or interruptions, you can use rex_get_sigs (), rex_set_sigs (), rex_clr_sigs () to perform signal operations on a task. When task
When a signal is set to Task B, the task also stores some data in a specific buffer. If a signal is set, task scheduling is triggered, task B receives this signal and is in the ready state. Once Task B has a high priority enough to run, Task B can read data from the buffer, thus realizing communication between tasks. The signal is stored in the task's own TCB, thus realizing the purpose and security of signal transmission.
Rex also provides the timer function. There are two types of Timer: clock timer and custom timer. When clk_timer arrives, it calls back the call back function and immediately executes the desired operation. The custom timer does not. It sets only one signal. If it is not executed, it depends on the priority of the task. Timer can be customized through rex_set_timer. Timer operations include rex_get_timer, rex_resume_timer, rex_cls_timer, rex_pause_timer, and rex_timed_wait.
Every tick of the system's clock will check whether the timer has arrived. Rex maintains a special list to store the timer. Once the timer expires, Rex will remove the timer from the list, but it is not deleted, only Rex does not know the existence of this timer. Timer can only be created and owned by tasks. Note that rex_set_timer cannot be called on an active timer. The cyclic timing detection of the program is based on the existence of timer, which enables the operating system to respond to events in discrete time in a timely manner.
When a timer arrives, or other signal settings may cause task scheduling, the concept of interruption must be mentioned in task scheduling. As the name suggests, an interrupt is to interrupt the current operation to perform other operations. The operating system will execute an interrupt at intervals to check whether the highest priority of the current ready-state task is the current task, or the task is interrupted spontaneously. That is, call rex_wait. Since the interruption will damage the running of the current task, but when a piece of code cannot be interrupted, it is necessary to execute the Guanzhong disconnection operation. This code is called the critical code segment. After executing this code segment, immediate interruption is also required. If task a voluntarily wait after the disconnection is executed, the disconnection will be stored without affecting the next task.
When a runs again, the disconnection status is restored. Pay attention to the following issues: 1. do not operate too much in the interrupted code; 2. do not use loops or wait for interruptions; 3. do not change the global variable when the task is interrupted, which may cause execution errors of the suspended task. 4. clk_tick_isr is also interrupted.
In the operating system, you must consider the issue of mutual exclusion and resource sharing. If both of them want to cross a river, but there is only one wooden Bridge on the River, if both of them occupy this bridge at the same time, neither of them can cross the river. This involves the concept of mutual exclusion. Rex provides the concept of critical section and mutual exclusion. In particular, we note that the critical code is disconnected to achieve mutual exclusion. In fact, the resource mutex between tasks can also be solved by semaphores. In this case, there is a problem: if there are three tasks, their priority order is as follows: task a> Task B> task C, task C runs first, it occupies the task
A's resources. At this time, task a is in the suspend State because it does not get the resources. In the process of running task C, Task B is ready, the system suspends task C during the interruption and runs Task B. In this way, the priority is reversed. The solution to this problem is to dynamically change the priority, that is, to increase the priority of task C. Rex supports a dynamic change of priority, but this can only be done after careful consideration, because the priority is strictly defined, and once changed, it may cause unpredictable consequences. The dynamic definition of priority is implemented through priority inheritance, that is, task C inherits the priority of task.
Rex has a strong storage zone protection function, which stores some important information in NV. Read Information from NV During task execution for the task. The hardware of the embedded operating system must be very small. Rex stores all static variables in a zone, and then the space required by each task, followed by the storage zone of dynamic variables, the size of the storage area should be implemented by the programmer, so that the programmer can reasonably arrange the size of the space used. Generally, the stack size of a task is determined. Therefore, a large array or struct cannot be used in the task, because the stack where the task is located will pop up.
If (rex_best_task = rex_curr_task)
Return;
Else if (the system is currently servicing interrupts)
{
Rex_curr_task = rex_best_task;
}
Rex_curr_task = rex_best_task;
Rex_start_task (rex_best_task );