The μC/OS-II operating system is a preemptive multitasking, single memory space, microkernel embedded operating system with efficient and compact characteristics. It has high execution efficiency, occupies little space, is highly portable, has good real-time performance, and strong scalability. Using the μC/OS-II real-time operating system can effectively schedule tasks; assigning different priorities to tasks ensures timely responses; adopting a real-time operating system reduces program complexity and facilitates program development and maintenance. The μC/OS-II is very suitable for application in some small embedded product scenarios, with widespread applications in household appliances, robotics, industrial control, aerospace, and military technology.
Combining microcontrollers, ARM, FPGA with the μC/OS-II operating system to achieve specific functions is currently quite common in embedded applications. In these applications, the foundational work is the porting of the operating system. This article introduces three commonly used processors: the 51 microcontroller, LPC2210, and NiosII.
1 μC/OS-II Operating System Porting Conditions
Most of the source code of the μC/OS-II operating system is written in C, but assembly language is still required to perform some processor-related operations, such as reading and writing processor registers, which can only be implemented using assembly language. Therefore, porting the μC/OS-II operating system to the target processor requires consideration from both hardware and software perspectives.
From the hardware perspective, the target processor must meet the following conditions:
① The C compiler of the processor can generate reentrant code;
② Interrupts can be enabled/disabled using C;
③ The processor supports interrupts and can generate timer interrupts (usually between 10 and 1000 Hz);
④ The processor can support a certain amount of data in the hardware stack;
⑤ The processor has instructions to read and store the stack pointer and other registers to the stack or memory.
From the software perspective, the focus is mainly on the porting of processor-related code, which is distributed across three different files: OS_CPU.H, OS_CPU_C.C, and OS_CPU_A.ASM.
2 Target Processor Hardware Support
The 51 microcontroller, LPC2210, and NiosII processors can all meet the porting requirements of the μC/OS-II operating system in terms of hardware.
51 Microcontroller: The Keil integrated development environment is chosen as the development tool because its C51 compiler can generate reentrant code and can enable/disable interrupts using C. It also has a certain number of stack and instructions related to the operation of registers.
LPC2210: The ARM7 microcontroller meets the above conditions ②, ④, and ⑤, while the ADS1.2 C compiler meets the requirements of ① and ③.
NiosII Processor: The Nios processor can be configured to support up to 64 interrupts, including external hardware interrupts, internal interrupts, and TRAP (debug interrupts). The Nios II processor can be configured to use a 32-bit internal timer, generating timer interrupts by controlling several control registers with software, which works similarly to general timer principles. The Nios processor can connect external memory. For example, the DE2 development board can connect to 512 KB of SRAM resources, providing sufficient data hardware stack.
NiosII 8.0 IDE uses the GNU compiler, supporting C/C++ compilation and linking to generate reentrant code, allowing assembly language to be embedded in C.
3 Software Porting Process
3.1 Implementation of OS_CPU.H
The OS_CPU.H file includes processor-related constants, macros, and data types defined using #define. The definitions of data types are the same across the different compilers used by the three processors, so they will not be specifically introduced here.
The macros related to the processor defined in OS_CPU.H are mainly OS_ENTER_CRITICAL() for entering the critical section and OS_EXIT_CRITICAL() for exiting the critical section.
In the Keil compiler, EA is the global interrupt.
#define OS_ENTER_CRITICAL() EA=0;//disable interrupts
#define OS_EXIT_CRITICAL() EA=1;//enable interrupts
In the ADS compiler, it is defined as a software interrupt function, and software interrupt handling code is written to implement enabling/disabling interrupts.
_swi(0x00)viod OS_TASK_SW(viod);//task-level task switching function
_swi(0x00)viod OS_ENTER_CRITICAL(viod);//disable interrupts
_swi(0x00)viod OS_EXIT_CRITICAL(viod); //enable interrupts
In the NiosII 8.0 IDE compiler:
#define OS_ENTER_CRITICAL() asm(“PFX 8
WRCTL%g0;”) //disable interrupts
#define OS_EXIT_CRITICAL() asm(“PFX 9
WRC TL%g 0;”) //enable interrupts
The growth direction of the stack is determined by setting OS_STK_GROWTH to 0 or 1. In the 51 microcontroller, it can only be set to 0, indicating that the stack grows from bottom to top. In LPC2210, it can be set to either 0 or 1. In NiosII, it can only be set to 1, indicating that the stack grows from top to bottom.
3.2 Implementation of OS_CPU_C.C
In OS_CPU_C.C, the stack initialization function OS-TaskStkIint() should be rewritten. It must be initialized according to the task stack structure defined during porting; the other 9 hook functions only need to be described. The corresponding operational code can also be written based on the user’s needs during porting.
Taking LPC2210 as an example, the stack space stores PC, LR, R12, R11, …, R1, R0, CPSR, OsEnterSum from high to low. Each task has an independent OsEnterSum, which saves and restores its respective OsEnterSum value during task switching. The interrupt enable/disable state of each task can be different, thus achieving nested interrupt enabling/disabling.
For the porting of the 51 microcontroller and NiosII processor, please refer to the references.
3.3 Implementation of OS-CPU-A.ASM
This part requires operations on the processor’s registers, so it must be written in assembly language. The μC/OS-II porting requires the user to write four simple assembly language functions: OSStartHighRdy(), OSCtxSw(), OS-IntCtxSw(), and OSTickISR().
The task of OSStartHighRdy() is to perform task scheduling and switching; OSCtxSw() is responsible for forcing the CPU to switch registers and the program counter; OSIntCtxSw() is responsible for task switching when returning from an interrupt; and OSTickISR() is the clock tick interrupt service routine used to implement time delays and timeout functions.
Taking the OSStartHighRdy() task scheduling and switching function as an example, the porting code for the three processors is introduced.
51 Microcontroller
OSStartHighRdy:
Conclusion
The 51 microcontroller, LPC2210, and NiosII processors have a broad market prospect in current embedded applications. Porting the μC/OS-II operating system to these three and other processors can better ensure the stability and real-time performance of the system during operation, and this operating system has less code, making it easy to master and port.
The porting of the μC/OS-II operating system to three processors introduced in this article is a summary and organization made by the author during the actual learning process, which has certain reference value for beginners.
1.Seven Habits You Must Have to Get Started with Linux!
2.Common Algorithm Analysis in Embedded System Languages, Remember These 12 Guidelines!
3.Three Heights of Career Planning for Microcontroller Engineers, Choose for Yourself!
4.Gartner’s 10 Predictions for the Technology Industry, Many Have Hidden Relationships with Embedded Systems!
5.The End of the Smartphone Era, Where Will the Next 10-Year Tech Battlefield Be?
6.Application Scenarios and Security Challenges of Blockchain
Disclaimer: This article is a network reprint, and copyright belongs to the original author. If there are copyright issues, please contact us, and we will confirm copyright based on the copyright certificate you provide and pay remuneration or delete content.