1980 views|0 replies

2015

Posts

0

Resources
The OP
 

Implementation of Embedded RTOS on MSP430 MCU [Copy link]

  With the development of information society, information appliances, smart meters and smart security systems have increasingly appeared in people's lives. It can be foreseen that in order to meet people's needs for a comfortable, convenient and safe living environment, the design and application of embedded information products will develop rapidly.

  As an important application of embedded information products, the use and design of single-chip microcomputers are facing new challenges. On the one hand, people have higher and higher requirements for embedded products, and stable, reliable, feature-rich, high-quality and low-cost information products will become people's first choice. On the other hand, with the development of microelectronics technology, the capabilities of single-chip microcomputer processors have been continuously improved, from the initial 8-bit single-chip microcomputer to 16-bit, and then 32-bit single-chip microcomputers, with more and more powerful functions, faster execution speed, higher integration and accuracy, and further expansion of application areas. It can be said that the performance of single-chip microcomputer chips can meet the higher requirements of modern people for embedded information products. In order to effectively combine the two, the software design method of embedded RTOS has also replaced the previous foreground and background (super loop) design method, and has been increasingly valued and applied.

  Just as the emergence of Linux in the time-sharing operating system broke the situation where Windows dominated the world, the emergence of uC/OS-II (Micro C OS 2) designed and written by Mr. Jean J.Labrosse of the United States also brought surprises to domestic RTOS users. The biggest advantage of uC/OS-II is the same as Linux, that is, its source code is fully open, so that people can clearly understand the internal implementation details while applying it, and can transplant and modify it according to their own needs. What is particularly important is that after 8 years of development, uC/OS-II has been successfully applied in many industries, ensuring practicality and reliability. Its emergence has changed people's attitude towards using RTOS in the past, reduced economic concerns, and will play an important role in promoting the research, promotion and application of domestic RTOS. uC/OS-II adopts a microkernel design and is written in C language. It pursues flexibility, is configurable, tailorable, expandable, and has strong portability. It should be emphasized that uC/OS-II strictly adopts a priority preemptive scheduling scheme. When creating a task, assign different priorities to each task according to its importance. When scheduling tasks, high-priority tasks are executed first, and then tasks are executed in descending order of priority. If a task with a higher priority is triggered during the execution of a task, then after the execution of the task is completed, the task scheduler will schedule the execution of the triggered high-priority task instead of executing it sequentially.

  The following discusses some problems that may be encountered in implementing RTOS on a microcontroller based on the transplantation and application of uC/OS-II on the MSP430F148 chip produced by TI.

  1 Introduction to MSP430 Series MCU

  The MSP430 series of microcontrollers are 16-bit microcontrollers developed by TI. Its outstanding feature is ultra-low power consumption, which is very suitable for various occasions with low power requirements. There are multiple series and models, each of which is composed of some basic functional modules according to different application goals. Typical applications are flow meters, smart meters, medical equipment, and security systems. Due to its high performance-price ratio, its application has become increasingly widespread.

  MSP430F148 is one of the MSP430F14x/13x series microcontrollers recently launched by TI. Compared with other chips in the MSP430 series, its main features are as follows:

  Ultra-low power consumption. With built-in ultra-low power fast flash memory, the MSP430F14x/13x series consumes less power in standby mode than the natural loss of the battery when not in use. Under normal working conditions, if the operating voltage is 2.2 V, the typical current consumption is only 250uA/MIPS, and the operating current in standby mode drops to less than 1uA.

  Fast execution speed. The MSP430F13x/14x series operates in the 1.8~3.6 V voltage range and can achieve up to 8 MIPS performance.

  Large storage capacity. The MSP430F148 has 48 KB Flash ROM and 2 KB RAM built in. The RAM space is the largest in the MSP430 series and basically meets the needs of running RTOS.

  High-performance A/D. Contains a 12-bit high-performance A/D converter with 8 external channels. With the chip's built-in auto-scan function, the A/D converter can work independently without the assistance of the central processor.

  High integration. The device also includes an independent watchdog, two pulse width modulation timers (PWM), a comparator, two USART ports and 48 input/output pins.

  Strong online support. The MSP430F13x/14x series can be supported by the MSP-FET430P140 Flash Emulation Tool (FET). The FET is a complete integrated development environment that includes a source code level debugger, emulator, assembler/connector, C compiler, 2 evaluation chips, target board, JTAG interface, and programming unit.

  From the above introduction, it can be seen that MSP430F148 is a mid-to-low-end MCU that only has the basic conditions for running RTOS. Therefore, some of the problems encountered when running RTOS on it are representative for general MCUs.

  2 Interrupt stack structure design

  In uC/OS-II, task switching is divided into task-level switching and interrupt-level switching. Task-level switching is accomplished by issuing soft interrupt instructions or relying on the processor to execute trap instructions. Soft interrupt instructions will force some processor registers to be saved to the stack of the current task and perform task scheduling. Its purpose is to make the stack structure of the task in the ready state look like an interrupt has just occurred and all registers are saved in the stack. For example, MCS-5l and x86 chips have similar instructions, but the problem is that some microcontroller chips do not have soft interrupt instructions, and the situation of saving registers when an interrupt occurs varies greatly depending on the microcontroller chip and the compiler used.

  There is no soft interrupt instruction in MSP430F148, and the IAR compiler used does not save all registers when an interrupt occurs, but only saves a few registers used in the interrupt. All of these do not meet the porting conditions of uC/OS-II. Our solution is to define an interrupt structure according to the specific situation. Whether it is task-level scheduling or interrupt occurrence or scheduling and task stack initialization, it must be executed according to this structure. The cost is that the assembly code of the interrupt program must be manually modified to make it conform to this interrupt structure.

  In order to design an interrupt stack structure that meets the requirements, we must first know what operations the microcontroller used performs when an interrupt occurs, that is, which registers are saved in the stack and their order. When an MSP430 microcontroller is interrupted, only two basic operations are performed. First, the SR (status register) is pushed into the stack for storage, and then the PC value of the next instruction to be executed when the interrupt occurs is pushed into the stack for storage. Secondly, we must know what default operations the C compiler used performs when compiling the interrupt program written in C language. By analyzing the assembly program compiled by the IAR V2.13 compiler used, it can be found that in addition to the above two basic operations, at the beginning of the interrupt program, four registers R12~R15 are automatically saved, and the remaining eight registers R4~Rll only save individual registers used in the interrupt program, not all. However, all registers must be saved in RTOS so that the status of the task can be correctly saved. Through the above analysis, we define the interrupt stack structure when MSP430 runs uC/OS-II, as shown in Figure 1.

  3 How to ensure the low power consumption of microcontrollers

  The application of microcontrollers in embedded systems emphasizes the ultra-low power consumption of microcontrollers. This is also the characteristic of the MSP430 series. If the low power consumption of the microcontroller is destroyed due to running RTOS, it will not be worth the loss. Generally, microcontrollers have several working modes with different power consumption, which can be selected according to specific needs. Different working modes are realized by reading and writing one or a group of registers to control the operation of the CPU, clock, crystal oscillator and peripheral devices.

  The MSP430 series microcontroller has 6 different working modes, all of which are realized by reading and writing the status register SR. In RTOS, since each task can save its own status, including the status register, it is more flexible and convenient to realize the low-power working mode. First of all, when designing each task, its working mode can be defined according to the specific requirements of the task. Secondly, in the entire system design, a task with the lowest priority is designed, and its role is to make the system enter a specific low-power working mode. In this way, after all other tasks have finished running, the system will call this task to make the entire system enter a low-power working mode. When other tasks resume running (such as when the delay ends), they will automatically enter their specific working state to achieve the purpose of reducing power consumption.

  4 How to reduce the RAM space occupied by RTOS during operation

  The main reason that affects the application of RTOS on MCU is that running RTOS on MCU requires certain system resources, such as system clock, RAM, FLASH or ROM, which reduces the utilization of resources by the application system. Especially the occupation of RAM. Generally speaking, the amount of internal RAM on the MCU 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 be expanded. Therefore, the best way is to make full use of the internal RAM of the MCU to run RTOS.

  By analyzing the use of RAM by uC/OS-II, we can know that the reason why the most RAM space is occupied is that when designing uC/OS-II, a separate task stack is allocated to each task. Especially when the hardware design of the microcontroller 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 by the variables and function nesting in the task, but also to calculate the size of the RAM space required for the interrupt and interrupt nesting of the task during operation. Since each task needs to reserve the size of 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 interrupt stack and task stack means that a special area in the memory is opened up as the interrupt stack, and any interruption that occurs during the running of a task only uses it. The design principles are: first, to separate interrupt tasks from ordinary tasks as much as possible; second, the simulated interrupt stack pointer must always remain at the top of the interrupt stack, that is, the interrupt stack pointer must always keep the same change as the SP during an interrupt.

  In order to achieve this goal, the microcontroller chip must meet the following two conditions.

  First, the MCU chip must have a general register and corresponding instructions to simulate the function of the stack pointer SP, that is, to implement a soft stack. In the MSP430 series MCU, there are the following instructions that can simulate the function of SP (using R4 as the interrupt stack pointer):

  MOV @R4+, SP; store the content of the address pointed to by R4 into SP; and add 2 to the content of R4

  MOV SP, 0 (R4); store the contents of SP into the address pointed to by R4

  MOV @R4+, PC; store the content of the address pointed to by R4 into PC; and add 2 to the content of R4

  Secondly, register R4, which is used as the pointer of the simulated interrupt stack, must not be used in any case other than an interrupt. This is because R4 must always be kept at the top of the interrupt stack. 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.

  In the specific design, we add 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 state saved by the task on the interrupt stack.

  FromInt flag: whether it comes from the interrupt flag. It is used to determine whether the task status is saved in the interrupt stack (1) or in the task stack (0).

  Assume that a common task 1 is interrupted during execution and analyze several possible situations that may occur during the interrupted execution.

  (1) When normal task 1 is running, an interrupt is triggered. During the interrupt, no higher priority task is activated. Instead, the interrupt ends normally and task 1 continues to execute, as shown in Figure 2.

Start interrupt: Move the SR and PC saved in the current task stack when the interrupt occurs to the interrupt stack for storage, and return the SP to the position before the interrupt and save it to the TSP in the task TCB (this is to maintain the continuity of the task stack after the interrupt ends), then point the 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 set the FromInt flag 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 point to the task stack of the task again, and finally, the PC pointer will point to the return address before the interrupt, and the program will continue to run.

  (2) When normal task 1 is running, an interrupt is triggered, and the higher priority task 2 is activated in the interrupt. When the interrupt ends, the task scheduler schedules the execution of the higher priority task 2 without returning to normal 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 Task 1 to execute according to the priority. By judging the FromInt flag in the TCB of Task 1, we can know 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 to the bottom of the interrupt stack. 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 in the interrupt, a higher priority task 2 is activated. When task 2 is being executed, another interrupt occurs, and during the interrupt, task 2 is suspended because it is waiting for a semaphore.

  This situation was prohibited when the system was originally designed, and the use of semaphores to suspend interrupts was not allowed.

  (5) When normal task 1 is running, an interrupt is triggered, and the higher priority task 2 is activated in the interrupt. When task 2 is executing, another interrupt occurs, and the higher priority task 3 is activated in the interrupt. When the interrupt ends, the task scheduler schedules the execution of the higher priority task 3.

  This situation is the same as situation 2 discussed.

  (6) High-priority task 2 is terminated by higher-priority task 3. After task 3 is finished 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 is automatically released. The other is that Task 2 is suspended by another task. In this case, a piece of code should be added to the function TaskSuspend() 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 within interrupts.

  When interrupt nesting occurs, it must 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 be scheduled and executed before the last interrupt exits. This is guaranteed by the uC/OS-II system design. Secondly, all the RAM bytes occupied by save registers and function calls are in interrupt nesting. When exiting interrupt nesting, it is not necessary to reset the FromInt flag in TCB.

  5 Programming Process

  (1) The interrupt program structure and design process are shown in Figure 4.

  (2) The task switching program flow between common tasks is shown in Figure 5.

  (3) The task switching program flow during interruption is shown in Figure 6.

  We have successfully run uC/OS-II on MSP430F148. With only 2 KB of RAM, we can run 16 tasks, which can meet some complex application requirements, greatly expand the application scope of MSP430F148, and improve the real-time performance of the application system. In order to verify the actual effect, on this basis, we integrated several commonly used household meters - water meters, heating meters, and hot water meters, and the operation effect was good, meeting the design requirements.

This post is from Microcontroller MCU
 

Guess Your Favourite
Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

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