At present, RTOS, especially preemptive RTOS, is increasingly widely used in embedded systems, but a large part of products still use small single-chip microcomputers. Due to cost constraints, these systems usually have very limited resources, such as ROM is often as small as 32 KB and RAM is less than 2 KB. Since RTOS has to open a separate memory area for each task to store the task context and the independent stack of each task, it is very difficult to use RTOS in such systems. For these low-cost resource-constrained systems, the "foreground and background" (or "super loop") structure is usually used for programming. This is actually an event-triggered programming model. When the number of interrupts is large and the functions completed by the system are relatively complex, the system programming becomes very complicated and the predictability of the system operation decreases rapidly.
In response to this problem, Michael J. Pont proposed a "time-triggered programming model", which helps to reduce the CPU load and reduce the memory usage, improve the predictability of system behavior, and make the program structure simple. However, in actual use, when different tasks in the system have different time requirements, the "time-triggered programming model" is difficult to provide a simple and effective solution. Therefore, the “time-triggered programming model” is improved to make it more adaptable and can provide a unified and effective programming model for small embedded systems with limited costs and resources.
1 Limitations of traditional programming structures
When RTOS is not used, embedded software usually uses two traditional programming structures for programming. One is called "front-end and back-end hall style" or "super loop structure", which is essentially an event-triggered programming method; the other is called time-triggered programming mode, and Michael J. Pont's "time-triggered programming mode" belongs to this.
In actual work, when the system is slightly complex, it will be found that both methods have certain limitations. The following is an example of a problem encountered in actual product design. When designing a wall-mounted intelligent power distribution meter for a power distribution cabinet, the CPU program design needs to complete the following tasks:
① Refresh the display data on the front display screen every half second.
② Refresh DI/DO every 0.1 s.
③ Scan the keyboard every 0.2 s.
④ Recollect and calculate the measured data every half second.
⑤ The asynchronous serial port communicates with the host computer using Modhus, with a maximum rate of 19,200 bps.
⑥ The CPU communicates with the clock chip and EEPROM through the I2C bus.
⑦CPU communicates with LED digital tube and acquisition chip through SPI bus.
⑧CPU needs to perform FFT transformation on the 6 channels of signals collected.
⑨When the system loses power, the CPU needs to respond quickly and write the current electricity base into EEPROM.
Among the above tasks, tasks ⑤ and ⑨ are highly real-time. If the serial port's receiving and sending events are not responded to in time, bytes will be lost when receiving, and the time interval between bytes will be too large when sending, resulting in Modbus frame delimitation errors on the receiving side. If the system power-off event cannot be responded to in time, the writing of EEPROM will fail. Other tasks can be executed within the specified cycle, but task ⑧ is special. It uses a common 8-bit CPU to perform FFT transformation on 6 signals. Even if each signal only performs 128-point FFT, it takes several seconds to calculate once. Let's look at the troubles encountered when implementing the above design using traditional programming structures.
1.1 Programming with "foreground and background mode"
When programming with "foreground and background mode", in order to ensure the timeliness of task ⑤, UART interrupt is used. When UART completes the transmission and reception of a byte, an interrupt is generated. In the interrupt program, the received character is saved in the receiving buffer or the next character to be sent is taken from the sending buffer and loaded into UART for transmission. The processing of Modbus protocol can be processed by a separate task outside the interrupt, which ensures the brevity of the interrupt program. In order to ensure the timeliness of task ⑨ response, an interrupt must also be arranged for it. Because when the system loses power, the system has less than 10 ms of transition time. If the system cannot complete the relevant operations within this time, the system voltage will drop below the effective voltage and lose its working ability.
After arranging the background interrupt task, let's see how the foreground task is completed. The biggest challenge here is the processing of task ⑧, because task ⑧ takes too long to execute. Simply treating it as a task will affect the system's response to other tasks. The code structure in the super loop is as follows:
while(1){
task ①;
task ②;
...
task ⑧;
}
Since task ⑧ takes several seconds to execute once, the entire super loop takes at least longer than the time required for task ⑧ to execute once. In other words, this super loop takes several seconds once, which will not meet the response time requirements of each task.
To solve this problem, we can only split Task ⑧ into many subtasks, compress the time of each subtask to about 10 ms, and define the status of each subtask after completion. In the super loop, only one subtask is executed each time according to the status. The program structure is as follows:
while(1){
Task ①;
Task ②;
…
switch(subtask status){
case subtask status ①:
subtask ①;
break;
…
case subtask status ②:
subtask ②;
break;
…
case subtask status:
subtask;
break;
}
}
In this way, a FFT operation task that takes several seconds needs to be split into hundreds of subtasks that take about 10 ms, which is obviously unacceptable. In addition, an implicit disadvantage of the super loop structure is that as the number of tasks increases, the execution time of the loop body increases linearly. In actual design, even if there is no time-consuming task like Task ⑧, it is still a challenge to ensure the timeliness of system response when the system functions increase. [page]
1.2 Programming with the "Time Triggered Programming Mode"
The core of the "Time Triggered Programming Mode" is to establish a cooperative task scheduler based on time triggering, minimize event triggering in the system (reduce the use of interrupts), and the system completes the scheduling and execution of each task through the task scheduler. The following is a typical program structure of the "Time Triggered Programming Mode": Each task in the system has defined priority, task cycle period and task delay time. The system timer interrupt program SCH Updatc() refreshes the task queue according to the set beat. In the super loop, only the task scheduler SCH_Dispatch_Tasks() is executed to arrange the execution of tasks according to the status of the task queue. This programming structure avoids the problem that the cycle time of the super loop structure increases linearly with the increase of the amount of code. However, since the task is non-preemptive, once the task is started, the task scheduler will have the opportunity to execute only after the current task is completed. This requires that the time each task occupies the CPU cannot be too long, otherwise it will affect the response speed of the entire system. Therefore, FFT operation must be effectively split in this programming mode, otherwise the CPU must be upgraded or a preemptive RTOS must be used, which will inevitably increase the system cost. Is there a better solution? The following programming structure "Time Triggered Programming Mode" has been improved to enable programmers to define tasks more intuitively without increasing hardware costs, reduce the impact of task characteristics on the system program structure, make the program structure simple and clear, and improve the real-time response speed of the system.
2 Improvements to the "Time-Triggered Programming Mode"
Based on many years of experience in embedded system programming, the tasks of embedded systems can usually be divided into three types:
① Timely tasks. This type of task is event-triggered. Once an event occurs, the system must respond within a limited time. For this type of task, the most natural way is to use interrupts to complete it, that is, it is defined as a background task in the "foreground and background mode".
② Periodic tasks. This type of task is time-triggered and periodic. The system must ensure that the task is executed within the specified period. The "time-triggered programming mode" can well meet the needs of this type of task. ③ Background tasks
. This type of task is non-real-time, and real-time performance is not very important. The system can interrupt this type of task at any time during operation to execute the first two types of tasks. As long as the system can make full use of resources to complete this type of task as quickly as possible, this type of task is most suitable for being defined as a foreground task in the "foreground and background mode".
According to the above task classification, the improvement of "time-triggered programming mode" can be summarized into the following requirements:
◆Tasks are divided into 3 categories, with category 1 tasks having the highest priority and category 3 tasks having the lowest priority;
◆High-priority tasks can interrupt the execution of low-priority tasks, and tasks of the same level cannot deprive each other;
◆In actual design, in order to improve the predictability of the system, the number of category 1 tasks and the execution time of category 1 tasks should be minimized;
◆In order to reduce the occupation of system resources, the system does not allocate separate stack space for tasks.
The essence of the above improvements is to design a simple task scheduling mechanism with 3 priorities. High-priority tasks can interrupt low-priority tasks, and tasks of the same priority cannot deprive each other. The scheduling mechanism does not save task context and separate stack for each individual task, which can reduce the demand for system resources by this programming mode.
When a high-priority task in a preemptive RTOS interrupts a low-priority task, it will save the context of the low-priority task and save the local variables of the low-priority task in a separate stack of the task. If the system does not allocate a separate stack for the task, how can the execution environment of the low-priority task be restored after the high-priority task exits?
For this problem, we can refer to the interrupt processing mechanism and solve it in the following ways:
① Design a timer interrupt function in the system. The function of this function is to execute the scheduling of periodic tasks. This timer interrupt has the lowest priority among all interrupts.
② Design another timer interrupt function in the system. The function of this function is to refresh the task management queue of periodic tasks and provide support for task scheduling. The priority of this timer interrupt function is the second lowest in the system.
③ Periodic task is a function. The first operation of the function entry is to open an interrupt, allowing the task to be interrupted during execution in order to respond to timely tasks.
④ Background task is the code executed in the main function super loop. This code can be interrupted by timely and periodic tasks at any time. When there are no timely and periodic tasks in the system, the code of the background task will be executed cyclically.
Through the above measures, the program structure of the "Improved Time Triggered Programming Mode" is as follows: Conclusion Using the "Improved Time Triggered Programming Mode" for small embedded system programming is like using RTOS for programming. After the designer has planned the tasks, he can concentrate on the design of each task. The task's occupation of processor time can be managed uniformly by the system, reducing the coupling between tasks, making the product program design and modification concise and clear. The use of this programming mode has solved the complex design problems faced by the installed intelligent distribution meter, proving that this method is simple and effective. At present, this design mode only designs the task scheduler, and the variable transfer between tasks still needs to use global variables. If semaphores and message mechanisms can be added, then this mode will be more perfect.
Previous article:Design of ultrasonic heat meter based on MSP430FW42X single chip microcomputer
Next article:MCU USB Descriptor
- Popular Resources
- Popular amplifiers
- Learn ARM development(16)
- Learn ARM development(17)
- Learn ARM development(18)
- Embedded system debugging simulation tool
- A small question that has been bothering me recently has finally been solved~~
- Learn ARM development (1)
- Learn ARM development (2)
- Learn ARM development (4)
- Learn ARM development (6)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- Analysis of the application of several common contact parts in high-voltage connectors of new energy vehicles
- Wiring harness durability test and contact voltage drop test method
- From probes to power supplies, Tektronix is leading the way in comprehensive innovation in power electronics testing
- From probes to power supplies, Tektronix is leading the way in comprehensive innovation in power electronics testing
- Sn-doped CuO nanostructure-based ethanol gas sensor for real-time drunk driving detection in vehicles
- Design considerations for automotive battery wiring harness
- Do you know all the various motors commonly used in automotive electronics?
- What are the functions of the Internet of Vehicles? What are the uses and benefits of the Internet of Vehicles?
- Power Inverter - A critical safety system for electric vehicles
- Analysis of the information security mechanism of AUTOSAR, the automotive embedded software framework
- EEWORLD University ---- VLSI CADI - Theory
- CircuitPython 5.0.0 released
- dspPI controller program problem
- Canaan's K510 development board is now on the forum. Let's warm it up first and post it later.
- Last week: 100 sets of Pingtouge RISC-V development boards, invite you to play ~ Come quickly ~ Share with friends and win red envelopes
- HP laser printer original toner cartridges are useless if you don't open them after using them up.
- Problems caused by macros that IAR cannot find defaulting to 0
- help
- FPGA technology introduction and FPGA application fields
- Learn MSP430F5529 programming routines