2951 views|0 replies

2015

Posts

0

Resources
The OP
 

How to reduce the RAM space occupied by RTOS during operation [Copy link]

The main reason that affects the application of RTOS on single-chip microcomputers is that running RTOS on single-chip microcomputers requires certain system resources, such as system clock, RAM, FLASH or ROM, etc., thus reducing the utilization of resources by the application system. Especially the occupation of RAM. Generally speaking, the amount of internal RAM on single-chip microcomputers is very small (for example, MSP430F148 has the most RAM in the entire MSP430, but it is only 2 KB). Although the amount of RAM can be increased through external expansion, this not only increases the difficulty of design and product cost, but also sometimes makes the system application unable to expand. Therefore, the best way is to make full use of the internal RAM of the single-chip microcomputer to run RTOS. By analyzing the use of RAM by uC/OS-II, it can be seen that the reason why the most RAM space is occupied is that when designing uC/OS-II, a separate task stack must be allocated to each task. Especially when the hardware design of the single-chip microcomputer does not separate the interrupt stack from the task stack, when calculating the size of the task stack, it is necessary not only to calculate the RAM size used for variables and function nesting in the task, but also to calculate the RAM space required for interrupts and interrupt nesting during the operation of the task. Since each task needs to reserve the RAM space required for interrupts and interrupt nesting, a large amount of RAM space is wasted. The most direct solution is to use software to separate the task stack and the interrupt stack, so that when calculating the size of the task stack, only the RAM space required by the task itself needs to be calculated, thereby improving the efficiency of RAM use and adding more application tasks. The so-called separation of the interrupt stack and the task stack is to open up a special area in the memory for use as an interrupt stack, and any interruption during the operation of any task only uses it. The design principles are: first, to separate the interrupt task from the ordinary task as much as possible; second, the simulated interrupt stack pointer must always be kept at the top of the interrupt stack, that is, the interrupt stack pointer must always keep the synchronization change with the SP during the interrupt. In order to achieve this goal, the single-chip microcomputer chip must meet the following two conditions. First, the microcontroller chip must have a general register and corresponding instructions to simulate the function of the stack pointer SP, that is, to realize the soft stack. In the MSP430 series microcontroller, there are the following instructions to simulate the function of SP (using R4 as the interrupt stack pointer): MOV @R4+, SP; store the content of the address pointed by R4 into SP; and add 2 to the content of R4 MOV SP, 0(R4); store the content of SP into the address pointed by R4 MOV @R4+, PC; store the content of the address pointed by R4 into PC; and add 2 to the content of R4 Secondly, as the register R4 that simulates the interrupt stack pointer, it must not be used in any case other than the interrupt. Because R4 must always be kept at the top of the interrupt stack at this time. If its value is changed, the structure of the interrupt stack will be changed. Generally, this requirement is guaranteed by the compiler used. In the IAR compiler we use, there is an option to avoid using R4 and/or R5. During the specific design, we added the following items to the TCB (task control block) structure of each task in uC/OS-II: TSP--Task stack pointer. After an interrupt occurs, it points to the top of the task stack of the task. ISP--Interrupt stack pointer. If a task switch occurs during an interrupt, it points to the top of the task's state saved in the interrupt stack. FromInt flag--Whether it comes from the interrupt flag. It is used to determine whether the state of the task is saved in the interrupt stack (1) or in the task stack (0). Let's assume that an ordinary task 1 is interrupted during execution and analyze several possible situations that may occur during its interrupt execution. (1) When normal task 1 is running, an interrupt is triggered. During the interrupt, no higher priority task is activated. Instead, the interrupt is ended normally and task 1 is continued to be executed, as shown in the figure.
Start interrupt: Move the SR and PC saved in the current task stack when the interrupt occurs to the interrupt stack for storage. At the same time, SP returns to the position before the interrupt and saves it to the TSP in the task TCB (this is to maintain the continuity of the task stack after the interrupt ends). Then point SP to the top of the current interrupt stack and save all registers to the interrupt stack in the order of the custom stack structure. During the saving process, R4 must keep changing synchronously with SP, and the FromInt flag is set to 1. Exit interrupt: Since no higher priority task is activated, after the interrupt task is completed, the interrupt will be exited in the normal order, that is, the registers saved in the interrupt stack will be pushed out of the stack, the FromInt flag will be set to 0, SP will be re-pointed to the task stack of the task, and finally, the PC pointer will point to the return address before the interrupt, and the program will continue to run. (2) When ordinary task 1 is running, an interrupt is triggered, and a higher priority task 2 is activated in the interrupt. When the interrupt ends, the task scheduler will schedule the execution of the higher priority task 2 without returning to ordinary task 1. When executing task 2, the task scheduler will restore the state of task 2 saved in its own task stack and execute task 2. After execution, if no higher priority task is activated, the scheduler will schedule the execution of task 1 according to the principle of high and low priority. By judging the FromInt flag in the TCB of task 1, it can be known whether the state of task 1 is saved in the task stack or the interrupt stack, so that its state can be restored and continue to run. (3) When ordinary task 1 is running, an interrupt is triggered, and task 2 with a higher priority is activated in the interrupt. When task 2 is executed, another interrupt occurs. Since uC/OS-II strictly follows the priority preemptive principle for task scheduling, the priority of the task that saves the task status at the top of the interrupt stack must be higher than the priority of the task whose status is saved below it. When executing, it is executed sequentially from the top of the interrupt stack to the bottom. In this assumption, task 2 must be executed first, and then task 1, as shown in Figure 3. (4) When ordinary task 1 is running, an interrupt is triggered, and task 2 with a higher priority is activated in the interrupt. When task 2 is executed, another interrupt occurs. During the interrupt, task 2 is suspended due to waiting for a semaphore. This situation was prohibited when the system was originally designed. It is not allowed to use semaphores to suspend interrupts in interrupts. (5)When ordinary task 1 is running, an interrupt is triggered, and task 2 with a higher priority is activated in the interrupt. When task 2 is being executed, another interrupt occurs, and task 3 with a higher priority is activated in the interrupt. When the interrupt ends, the task scheduler schedules task 3 with a higher priority to be executed. This situation is the same as situation 2 discussed. (6) High-priority task 2 is terminated by task 3 with a higher priority. After task 3 finishes running, the task scheduler will directly schedule task 1 for execution (scheduling according to priority). Since the ISP and TSP of each task have been saved in the TCB of the task before the task switch, the stack pointer and R4 of task 1 can return to the correct position of the task in its task stack and interrupt stack. There are two situations in which task 2 is terminated. One is that task 2 is deleted by another task, in which case the space occupied by task 2 in the interrupt stack will be automatically released. Second, if Task 2 is suspended by another task, a piece of code should be added to the TaskSuspend() function that suspends the program to move the state saved in the interrupt stack to its own task stack, and set the FromInt flag in its TCB to 0. In this way, after Task 2 is unsuspended, its state will be restored in the task stack. (7) Interrupt nesting occurs in interrupts. When interrupt nesting occurs, it should be handled according to the interrupt nesting mechanism. First, task scheduling is not allowed in interrupt nesting. In this way, even if a higher priority task is triggered in interrupt nesting, it must wait until the last interrupt exits before scheduling and execution. This is guaranteed by the uC/OS-II system design. Secondly, all the RAM bytes occupied by registers and function calls are in interrupt nesting. When exiting interrupt nesting, it is not necessary to reset the FromInt flag in TCB.

This post is from Microcontroller MCU
 

Find a datasheet?

EEWorld Datasheet Technical Support

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
快速回复 返回顶部 Return list