Research on Embedded System Application Development Based on μC/OS
2026-04-06 05:57:45··#1
Abstract: This paper introduces the concept of embedded systems, analyzes the kernel structure of μC/OS, and details the porting of the μC/OS operating system and the development of application programs and drivers on the S3C44B0 microprocessor with ARM architecture. Keywords: Embedded system, μC/OS , Microprocessor I. Overview of Embedded Systems Embedded systems are products that combine advanced computer technology, semiconductor technology, and electronic technology with specific applications in various industries. Currently, embedded systems have permeated all aspects of daily life, and their application scope in industry, service industry, and consumer electronics is constantly expanding. The formal definition of an embedded computer system is: a dedicated computer system centered on applications, based on computer technology, with customizable software and hardware, and meeting the stringent requirements of application systems for functionality, reliability, cost, size, and power consumption. The main characteristics of embedded systems include: small system kernel; high specialization; system simplification; embedded software requires high real-time operating system software; software requires high quality and high reliability; embedded system development requires specialized development tools and environments. Embedded systems consist of two main parts: hardware and software. In this development application, the Samsung S3C44B0 microprocessor chip with an ARM7TDMI core architecture was selected. This chip features high clock speed, fast processing speed, ultra-low power consumption, low cost, and simple structure. Based on this core, a complete set of general-purpose peripheral devices were added, including: an on-chip 8KB cache, an LCD controller with one dedicated DMA channel, two general-purpose DMA channels, one multi-master I2C bus controller, five PWM timers and one internal timer, 71 general-purpose I/O ports, eight external interrupt sources, and eight 10-bit ADCs. The clock speed is 66MHz. The system supports endianness, has a total address space of 256MB, and supports 8/16/32-bit data bus programming. The development platform includes external user interfaces such as an RS-232 serial port, external flash memory, SDRAM, USB control circuitry, Ethernet circuitry, a keyboard, and a JTAG interface. There are many types of real-time embedded operating systems, which can be broadly divided into two categories: commercial and free. Commercial systems are stable and reliable, with comprehensive technical support and after-sales service, making application development relatively easy, but they are expensive. Representative examples include Wind River's VxWorks operating system and Microsoft's WinCE operating system. Free systems save costs, and their source code is open, facilitating development. Representative examples include embedded Linux systems and μC/OS systems. II. Introduction to the Architecture of Embedded μC/OS Due to the simple structure of μC/OS, most programming tools are in C language, allowing compilation into target code using most user-friendly compilers, such as Borland C and Keil. Its kernel can be as small as tens of kilobytes, making it portable to various microprocessor architectures. User workload is minimal, and the open source code facilitates learning. The main components of μC/OS-II include: The core (OSCore.c) is the processing core of the operating system, including operating system initialization, operating system operation, interrupt handling, clock ticking, task scheduling, event handling, and more. The task processing section (OSTask.c) handles task operations, including task creation, deletion, suspension, and resumption. The clock section (OSTime.c) primarily handles task delay operations. The task synchronization and communication section is the event handling section, including semaphores, mailboxes, mailbox queues, and event flags. The software architecture of μC/OS-II is shown in Figure 1. As can be seen from Figure 1, to use μC/OS-II, three files must be written: OS_CPU.H, OS_CPU_C.C, and OS_CPU_A.ASM. III. Porting μC/OS to ARM Microprocessors The total source code of μC/OS-II is approximately 6000-7000 lines, comprising 15 files. Porting μC/OS-II to an ARM processor is relatively simple, requiring only modification of three ARM architecture-related files, totaling approximately 500 lines of code. The following describes the porting process for these three files: The OS_CPU.H file defines data types. Modifications to this part are compiler-dependent; different compilers use different byte lengths to represent the same data type. The compiler used here is the ARM SDT 2.5 integrated visual development environment. The relevant data type definitions are as follows: #define BYTE INT8S /* Define data types for backward compatibility */ #define UBYTE INT8U /* .to uC/OS V1.xx. Not actually needed for . */ #define WORD INT16S /* ... uC/OS-II. */ #define UWORD INT16U #define LONG INT32S #define ULONG INT32U Stack unit: Because the processor's registers are saved in the stack of the currently running task during task switching, the OS_STK data type should be consistent with the processor's register length. typedef unsigned int OS_STK; /* Each stack entry is 16-bit wide */ The stack growth direction is determined by compiler options. In this development, the stack is set to grow from high address to low address. #define OS_STK_GROWTH 1 //define the stack to grow from high to low 2. Task stack initialization in OS_CPU_C.C file This involves a stack design during task initialization, that is, how to define the location of each register that needs to be saved in the stack growth direction. In the ARM architecture, the task stack space will store pc, lr, r12, r11, r10, ... r1, r0, CPSR, SPSR in descending order. void *OSTaskStkInit (void (*task)(void *pd), void *pdata, void *ptos, INT16U opt) { unsigned int *stk; opt = opt; /* 'opt' is not used, prevent warning */ stk = (unsigned int *)ptos; /* Load stack pointer */ *-stk = (unsigned int) task; /* lr */ ……; /* r12—r0 */ *-stk = ARM_MODE_SYS; /* system mode */ *-stk = ARM_MODE_SYS; /* system mode */ return ((void *)stk); } After the current task stack is initialized, OSTaskStkInit returns a new stack pointer stk, which will be called when OSTaskCreate() is executed. The initialization process is then performed, and the returned sp pointer is saved to the TCB block of the task through the OSTCBInit() function call. OSStartHighRdy() This function is executed after the main program OSStart() starts multitasking. It is responsible for obtaining the stack pointer sp of the highest priority task from the TCB control block of the highest priority task, and restoring the CPU context in sequence through sp. At this time, the system transfers control to the user-created task process. It is executed only once. After that, multitasking priority scheduling is performed by the following functions. OSCtxSw() Task-level context switching is executed when a task actively requests CPU scheduling because it is blocked. Since the task switching at this time is performed in non-exception mode, its work is to first save the CPU context of the current task to the task stack, then obtain the stack pointer of the highest priority task, restore the CPU context of this task from the stack, and make it continue to execute. `OSIntCtxSw()` is an interrupt-level task switch. It detects a high-priority task waiting for a clock signal in the clock interrupt service routine (ISR) and schedules the ready high-priority task to execute immediately after the interrupt exits. `OSTickISR()` is the clock interrupt handler function. Its main task is to handle clock interrupts, calling the system-implemented `OSTimeTick` function. If there are high-priority tasks waiting for a clock signal, they need to be scheduled for execution at the interrupt level. The other two related functions are `OSIntEnter()` and `OSIntExit()`, both of which need to be executed in the ISR. After porting the above program, users can write their own applications according to their project requirements. Users can add tasks such as printing and idle waiting. The following is an example program that registers three tasks by calling the `OSTaskCreate()` function, which are then scheduled by the system according to the optimal scheduling principle. void main (void) {Initialize(); /* Processor specific initialization */ OSInit(); bufferSemaphore = OSSemCreate(BUFFER_LENGTH - 1); terminalSemaphore = OSSemCreate(1); OSTaskCreate(Task1, (void*)string1, (void*)&stacks[0][TASK_STK_SIZE - 1], 0); OSTaskCreate(Task2, (void*)string2, (void*)&stacks[1][TASK_STK_SIZE - 1], 1); OSTaskCreate(Task3, (void*)string3, (void*)&stacks[2][TASK_STK_SIZE - 1], 2); OSStart(); /*Start..... */ } IV. Adding Drivers Since UC/OS only provides a task scheduling kernel, to obtain a relatively complete, real-time embedded multitasking operating system through the above porting, considerable expansion work is still required. This mainly includes: establishing a file system, developing drivers for devices such as LCD displays, USB communication, keyboards, and serial ports to provide API functions for application calls, and creating graphical user interface (GUI) functions. The following mainly introduces the development of the serial port driver. `void Uart_Init(int mclk, int baud) { }` This function mainly initializes the serial port and sets the baud rate, where `mclk` is the system main clock frequency, and the `baud` parameter passes the serial communication baud rate. `void Uart_Select(int ch) { }` This function selects the serial port; `ch` passes the serial port number. `char Uart_Getch(void) { }` This function reads characters from the serial port and stores them in an array. `void Uart_GetString(char *string) { }` This function reads the string to be sent and sends it character by character from the serial port. `void Uart_SendByte(int data) { }` This function sends data through the serial port; `data` is the character to be sent. `void Uart_SendString(char *pt) { }` This function sends a string through the serial port; `pt` is a pointer to the first address of the string. Through these interface functions, the system provides users with API functions that shield the underlying hardware, allowing users to easily operate the serial port. V. Conclusion Currently, there are many products on the market based on the μC/OS embedded operating system, with applications in industrial control, home appliances, network equipment, etc. Moreover, μC/OS-based applications are booming. With the advent of the post-PC era, embedded system theory and application research are advancing rapidly. μC/OS is a powerful tool for developing embedded systems. A good grasp of this technology can combine theory with practical application, better serving our daily lives and production. References: 1. Shao Beibei (trans.). μC/OS-II Open Source Real-Time Embedded Operating System [M]. Beijing: China Electric Power Press, 2001. 2. Wang Tianmiao. Embedded System Design and Example Development. Tsinghua University Press, October 2003. 3. Zou Siyi. Embedded Linux Design and Application. Tsinghua University Press, January 2002.