The limitations of the traditional programming structure, using the "front and back way" programming

1 Limitations of Traditional Programming Structures

When not using RTOS, embedded software usually uses two traditional programming structures for programming. One is called “front-back structure” or “super loop structure”. It is essentially an event-triggered programming method, and the other is called time. Triggered by the programming method, Michael J.Pont's "time-triggered programming mode" belongs to this.

In the actual work, when the system is slightly complicated, it will be found that both methods have certain limitations. The following is an example of the problems encountered in the design of an actual product.

When designing a wall-mounted intelligent power distribution meter for a power distribution cabinet, the CPU's programming needs to complete the following tasks:

(1) Brush the display data of the front display every half second.

(2) Refresh DI/DO every 0.1 seconds.

(3) The keyboard is scanned once every 0.2 seconds.

(4) The measurement data is re-acquired and calculated every half second.

(5) The asynchronous serial port communicates with the host computer using Modbus communication at a rate of up to 19200 bps.

(6) The CPU communicates with the clock chip and EEprom via the IIC bus.

(7) CPU communicates with LED digital tube and acquisition chip through SPI bus.

(8) The CPU performs FFT transformation on the collected 6 signals.

(9) When the system is powered off, the CPU needs to respond quickly to write the current power base to the EEprom.

In the above tasks, task (5) and task (9) are strongly real-time. If the serial port sending and receiving events are not timely responded, the bytes will be lost when receiving, and the time interval between bytes will be too large when sending. The Modbus frame delimiter of the receiver is incorrect. If the system fails to respond to the power-down event, the EEprom will fail to be written. Other tasks can only be executed within a specified period, but task (8) is special, using the usual 8-bit CPU to perform FFT transformation of 6 kinds of signals, even if each signal only performs 128-point FFT, operation once also A few seconds. Let's take a look at the problems encountered when implementing the above design using traditional programming structures.

1.1 Programming using "front-back-end mode"

When using “front-backend mode” for programming, in order to guarantee the timeliness of task (5), a UART interrupt is used. When the UART completes sending and receiving one byte, it generates an interrupt. In the interrupt program, the received character is stored in the receive buffer. The area can be loaded with a character to be sent from the transmit buffer and loaded into the UART. The processing of the Modbus protocol can be handled with a single task outside the interrupt. This ensures that the interrupt program is short. In order to ensure the promptness of the task (9) response, it must also be scheduled for an interruption. Because when the system is powered off, the system has a transition time of less than 10ms. If the system cannot complete the relevant operation within this time, the system voltage will drop below the effective voltage and lose its working ability.

After the background interrupt tasks are scheduled, let's take a look at how the front desk tasks are completed. The biggest challenge encountered here is the processing of task (8), because task (8) takes too long to execute. Simply treating it as a task will affect the system's response to other tasks, in the super loop. The code structure is as follows:

While(1)

{

Task (1);

Task (2);

.........

Task (8);

}

Since task (8) takes a few seconds to execute once, and the entire super loop executes at least one time longer than task (8), that is, this super loop loop takes several seconds at a time, it will not satisfy the response time of each task. The request.

To solve this problem, only split the task (8) into a large number of subtasks, compress the time spent on each subtask to about 10 milliseconds, and define the state of each subtask after completion, each time in the super-large loop. Only one subtask is executed according to the state, the program structure is as follows

While(1)

{

Task (1);

Task (2);

.........

Switch (subtask status)

{

Case subtask state 1:

Subtask 1;

Break;

Case subtask state 2:

Subtask 2;

Break;

............

Case subtask state n:

Subtask n;

Break;

}

}

In this way, it is necessary to split a FFT operation task that takes a few seconds into several hundred sub-tasks that take about 10 ms, which is obviously unacceptable.

In addition, one disadvantage of the super-large loop structure is that as the task increases, the execution time of the loop body increases linearly. Even if there is no high-time-consuming task like the task (8) in the actual design, It is also a challenge to ensure the timely response of the system when the system function increases.

1.1 Programming with "Time Triggered Programming Mode"

The core of "time-triggered programming mode" is to establish a time-triggered cooperative task scheduler to minimize event triggering in the system (reducing the use of interrupts). The system uses the task scheduler to complete the scheduling and execution of each task. The following is the Typical program structure of "time triggered programming mode":

/*--------------------Main Function -----------------------*/

Void main(void)

{

SCH_Init();//Set the scheduler

SCH_Add_Task (task function name, task scheduling delay, task scheduling period);//Join tasks to the scheduler's task queue

SCH_Start();//Refresh task queue

While(1)

{

SCH_Dispatch_Tasks(); //Perform the task scheduler

}

}

/*------------------- Timed interruption function ---------------------*/

Void SCH_Update(void) interrupt

{

// Refresh task queue

}

Each task in the system defines the priority, task cycle period and task delay time. The system timer interrupt program SCH_Update() refreshes the task queue according to the set beat. Only the task scheduler SCH_Dispatch_Tasks is executed in the super big loop. ), according to the status of the task queue to arrange the execution of the task.

This programming structure avoids the problem that the cycle time of the super-large loop structure increases linearly with the increase of the code amount. However, since the task is inalienable, once the task starts execution, the task scheduler has the opportunity to execute only after the current task is completed. This requires that each task occupy CPU time can not be too long, otherwise it will affect the overall system response speed. Therefore, the FFT operation must be effectively split in this programming mode. Otherwise, the CPU must be upgraded or the preemptive RTOS must be used. This will inevitably increase the system cost. Is there a better solution?

The following programming structure improves the "time-triggered programming mode" so that programmers can more intuitively define tasks without increasing hardware costs, and reduce the impact of task characteristics on the system program structure, making the program structure simple and clear. And improve the system's real-time response speed.

2 Improvements to "Time Triggered Programming Mode"

According to many years of experience in embedded system programming, the task of embedded systems can be divided into 3 types:

(1) Timely tasks;

(2) periodic tasks;

(3) Background tasks;

Timely task characteristics: This type of task is event-triggered. Once an event occurs, the system must respond within a limited time. The most natural method for such tasks is to use interrupts to complete the process. The background task in the mode.

The characteristics of periodic tasks: This type of task is a time-triggered periodic type. The system must ensure that the tasks are executed within a specified period. The "time-triggered programming mode" can well meet the needs of such tasks.

The background task features: This type of task is not real-time, real-time is not very important, the system can interrupt this kind of task at any time in order to perform the first two types of tasks in the running process, the system can make full use of resources as soon as possible to complete this quickly Tasks of this kind can be used. This kind of task is best suited to be defined as a foreground task in the "front and back mode".

According to the task classification above, improvements to the "time-triggered programming model" can be summarized as follows:

(1) The tasks are divided into 3 categories, with the highest priority for category 1 tasks and the lowest for category 3 tasks;

(2) High-priority tasks can interrupt the execution of low-priority tasks, and tasks of the same level cannot be mutually deprived of each other.

(3) In order to improve the predictability of the system in actual design, the number of type 1 tasks and the execution time of type 1 tasks should be minimized.

(4) In order to reduce the occupation of system resources, the system does not divide the stack space for tasks.

The essence of the above improvement is to design a simple three-priority task scheduling mechanism. High-priority tasks can interrupt low-priority tasks, and tasks of the same priority cannot be mutually deprived of each other. The scheduling mechanism is not for each individual. The task saves the task context and a separate stack, which reduces the need for system resources for this programming mode.

When a high-priority task in a separable RTOS interrupts a low-priority task, it saves the context of the low-priority task and saves the low-priority task's local variables in a separate stack on the task. Don't assign a separate stack to the task. How to ensure the recovery of the low-priority task execution environment after the high-priority task exits?

To solve this problem, we can use the following methods to solve the problem:

(1) Design a timer interrupt function in the system. The function of this function is to perform the scheduling of periodic tasks. The timer interrupt has the lowest priority in all interrupts.

(2) Designing another timed interruption 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 timed interruption function is lower in the system.

(3) A periodic task is a function whose first operation is to open an interrupt (Q: This interrupt refers to an interrupt that triggers a timely task. Then, outside the periodic task, is it on or off? If yes On,) allows the task to be interrupted during execution in order to respond to timely tasks.

(4) The background task is the code executed in the main function super loop. This code can be interrupted at any time by the time-based and periodic tasks. When the system does not have the time-based task or the periodic task, the background-type task code is executed cyclically.

Through the above measures, the program structure of "improved time-triggered programming mode" is as follows:

/*--------------------Main Function -----------------------*/

Void main(void)

{

SCH_Init();//Set the scheduler

SCH_Add_Task (task function name, task scheduling delay, task scheduling period);//Join tasks to the scheduler's task queue

SCH_Start();//Refresh task queue

While(1)

{

Background task 1;

.........

Background task

}

}

/*------------------- Second-lowest priority timer interrupt function ---------------------* /

Void SCH_Update(void) interrupt

{

// Refresh task queue

}

/*------------------- Minimum priority timer interrupt function ---------------------* /

Void SCH_Dispatch_Tasks(void) interrupt

{

// Dispatching periodic tasks

}

/*------------------- Typical Structure of Periodic Tasks ---------------------*/

Void SCH_Cycle_Task1(void)

{

/ / Open interrupt / * This function can be triggered by the interrupt to perform timely tasks * /

//Execute the task

Return;//task return

}

Conclusion

Using "improved time-triggered programming mode" for small-scale embedded system programming, just like programming with RTOS, after the designer has planned the tasks, he can concentrate on the design of each task. The task's occupation of the processor time can be The unified management of the system reduces the coupling between tasks, so that the product design and changes are simple and clear. The use of this programming model well solves the complex design issues faced by wall-mounted smart distribution meters and proves that the method is simple and effective.

At present, this design pattern only designs the task scheduler, and the variable transfer between tasks also requires the use of global variables. If we can add semaphores and message mechanisms, then this model will be more complete and will make the programming of low-cost small-scale embedded systems more efficient. Convenient and clear.

FM Transmitter

A personal FM transmitter is a low-power FM radio transmitter that broadcasts a signal from a portable audio device (such as an MP3 player) to a standard FM radio. Most of these transmitters plug into the device's headphone jack and then broadcast the signal over an FM broadcast band frequency, so that it can be picked up by any nearby radio. This allows portable audio devices to make use of the louder or better sound quality of a home audio system or car stereo without requiring a wired connection. They are often used in cars but may also be in fixed locations such as broadcasting from a computer sound card throughout a building.

Fm Transmitter,Fm Transmitter System,Personal Radio Fm Transmitte,Fm Stereo Transmitter

Anshan Yuexing Technology Electronics Co., LTD , https://www.yxhtfmtv.com