Professional Documents
Culture Documents
uCOS Theory
uCOS Theory
uCOS Theory
10)
management, memory management and other system service functions such as communication and synchronization between tasks [1]. The software architecture is shown in Fig. 1.
Tasks of COS-II Task 1 . Task N Idle Task
1. Introduction
Embedded operating system improves the reliability and development efficiency of the system. Moreover, it utilizes the potential of multi-task 32-bit CPU adequately. COS-II is a Real-time Operating System (RTOS) which is free of charge and source open. It is preferred due to many characteristics such as micro-kernel, multi-task management, preemptive scheduling, portability and kernel scalability, and it has been ported onto many processors: x86, 68k, ColdFire, MPC 8xx, ARM, MIPS, C5409 and so on.
Scheduling
Request/Response
Time Management
The main task of the COS-II kernel is to provide s system services for tasks. A task can request certain kinds of services of the kernel, then the kernel responses to corresponding requests. At the same time, the kernel executes the ready task with highest priority according to the state of the current task. The real-time is ensured by mechanism of preemptive task scheduling. 2.2 Portability of the kernel When the COS-II is originally created, the portability problem is considered. Much of COS-II code is written in C language, only machine-related parts are written in assembly language because C language is not able to read or write on registers directly. Processors must satisfy the following requirements in order to run COS-II smoothly [1]: (1) C complier can generate reentrant code;
(2) Interrupt can be disabled or enabled by C; (3) The processor must support interrupt and be able to generate timing interrupt; (4) The processor must support hardware stacks with data; (5) The processor must have instruction to load and store stake pointer and other registers to memory.
The architecture of COS-II is shown in Fig. 2. Porting COS-II consists of two major steps: writing processor dependent code OS-CPU.h and OS-CPU.c, the other step is to cut kernel depending on the configuration of application and hardware resource so as to lower the payload of the system.
Application Software
COS-II (Processor Independent Code) OS_CORE.C COS_II.C OS_TASK.C COS_II.H OS_SEM.C OS_MBOX.C OS_MEM.C OS_Q.C OS_TIME.C
Clock
Other Devices
software resources. It is needless to modify the kernel which is hardware-related and complier-related in the kernel of COS-II[1]. The main task of porting COS-II is to modify five functions related to hardware in file OS-CPU.c: OSTaskStkInit(), OSCtxSw(), OSIntCtxSw(), OSStartHighRdy(), TickISR() and the macro definition in OS-CPU.H: OS- ENTER-CRITICAL(), OS- EXIT-CRITICAL(), OSSTK-GROWTH, OS- TASK-SW(). 4.1 Steps of porting Step 1: Hardware initialization Upon resetting of MPC555, it starts at the entry point of reset function. The function mainly carries out the tasks as follows: the system basic stacks initialization, the floating instruction flag initialization, copying the data from ROM to RAM , and jumping to the system main function entry pointmain(), the major flowchart is as follows:
asm void -- reset (void) { Create the stacks which main() function is ready to use;
4. Porting COS-II
Porting COS-II needs to initiate the hardware resources, then jumps to the main() which initiates the
Analysis and Implementation of Porting -II to MPC555 COS Set floating instruction running flag MSR[FP]; Copy the data from ROM to RAM; Jump to the entry point of main(); }
Machine Status Register (MSR) Next instruction before interrupt (SRR0) Values of the system status registers before interrupt (SRR1) Function return address register (Link Register) Values of special register (SPR) Values of general register (GPR) Values of floating register(FPR) Fig. 3 Architecture of task stacks
Low Address
Stack Growth
High Address
When the task is created, it is necessary to create a virtual stack for the task, so that when the task starts, it looks like that there is an interrupt just now in the stack and the data of all registers are saved in the stack. Due to the 64-bit floating arithmetic unit in MPC555, the width of the stack must be set to 64 bits in order to save the data of floating registers[2]. The structure and content of the stack are shown in Fig. 3. According to the stack structure, the stack initialization function OSTackstInit() creates a virtual task stack, so that when the task is scheduled for the
first time, it is easy to restore the data of registers and make the task to go running. Step 3: Run the task with highest priority After the initialization of software in the system, it needs to call OSStartHighRdy() to run the task with highest priority. This function first sets the flag OSRunning which means that the system is starting running, then restores the data of all registers from the stack of which task is ready to run, and executes the instruction that the interrupt returns. The main flow is as follows [3]:
asm void OSCtxSw(void) { Restore value of SP from OSTCBCur - > OSTCBStkPtr; OSRunning = 1; Restore other CPU registers of this task ; mtspr NRI, gpr20 //disable interrupt and exception lwz gpr20, OFFSET-SRR0(SP) mtspr srr0, gpr20 //restore SRR0 lwz gpr20, OFFSET-SRR1(SP) srr1, gpr20 //restore SRR1 rfi PP //execute a return from interrupt //instructon }
Step 4: Task-level context switch The function OSCtxSw() which performs task-level context switch is called when some task gives up CPU time automatically. A task level context switch is accomplished by issuing a software interrupt instruction. The SC (System Call) of MPC555 can implement soft interrupt, and jump absolutely at its interrupt rector address. Then it could jump to the
entry point of OSCtxSw() function to switch the tasks. When the OSCtxSw() function begins, interrupt and exception are all disabled, the two registers of SRR0 and SRR1 will not change during the execution[4]. It is necessary to save the two registers as well as current values of other registers onto stack before enabling interrupt and exception. After saving the register values of current task, restore register values of new
task immediately. However, it is necessary to disable interrupt and exception when restoring the register values of MSK, SRR0, SRR1, otherwise the values of
asm void OSCtxSw(void) { mfspr gpr20 , srr0 stw gpr20 , OFFSET-SRR0(SP) mfspr gpr20 , srr1 stw gpr20 , OFFSET-SRR1(SP) mtspr EIE , gpr20 Save other registers of CPU; Get the task with highest priority which is ready-to-run; Restore other registers of CPU of this task; mtspr NRI , gpr20 lwz gpr20 , OFFSET-SRR0(SP) mtspr srr0 , gpr20 lwz gpr20 , OFFSET-SRR1(SP) mtspr srr1 , gpr20 rfi //instructon }
this three registers will change during the execution, and it can not restore the values saved in the registers[2]. The major flow is as follows:
// disable interrupt and exception //restore SRR0 //restore SRR1 // execute a return from interrupt
Step 5: Interrupt-level context switch Interrupt-level context switch is similar to task-level context switch. Interrupt-level context switch needs to call function OSIntExit() to exit interrupt, however, interrupt-level context switch is
Current SP
called within OSIntExit(). So, it is necessary to adjust the stack pointer when saving the pointer of task s stacks in order to take out the stacks which the complier generates during the call OSIntExit() and OSIntCtxSw(), it is shown in Fig. 4.
Low address
Return address to caller of OSIntCtxSW Return address to caller of OSIntExit Register values of SRR0/SRR1
Stack Growth
Save the current CPU register values Data in the stack before interrupt Fig. 4 Stacks during execution of ISR High address
The changes during calling OSIntExit() and OSIntCtxSw() are related to complier. It is the only place which is complier-related in the whole system. 4.2 Clock tick interrupt service Clock Tick interrupt service, whichCOS-II kernel must provide, executes before every clock tick interrupt. MPC555 Decrementer and periodic clock s interrupt(PIT) can both act as tick generator[1]. Decrementer is chosen as implementation. It has an
asm void TickISR(void)
independent interrupt vector offset address OX900. Jump absolutely at this interrupt vector address to execute TickISR(). TickISR() saves values of CPU registers of current task to stacks, and then executes the hardware independent clock tick handling function OSTimeTick(). And calling OSIntExit() to exit interrupt at the same time, then executes the task with highest priority. The key flowchart is as follows:
Analysis and Implementation of Porting -II to MPC555 COS { mfspr gpr20 , srr0 stw gpr20 , OFFSET-SRR0(SP) mfspr gpr20 , srr1 stw gpr20 , OFFSET-SRR1(SP) mtspr EIE , gpr20 Save other CPU registers; Call OSIntEnter () ; Call OSTimeTick() to handle clock interrupt; Initiate Decrementer again; Call OSIntExit () ; }
4.3 Hardware-related macro During the porting, it is necessary to change some macros which is related to CPU. OS- ENTER-CRITICAL( ) ,OS- EXIT-CRITICAL ( ) are used to e nable and disable interrupt, they are defined as follows [3]:
# define OS-ENTER-CRITICAL () asm {mtspr NRI gpr20 } # define OS-EXIT-CRITICAL () asm {mtspr EIE gpr20 }
OS-TASK-SW() defines the task-level context switch instruction, which is a soft interrupt instruction which is related to CPU, defined as follows:
# define OS-TASK-SW() asm {sc } References: [1] Jean J. Labrosse. (2002). MicroC/OS-II, The Real-Time Kernel. 2nd ed. CMP Books. [2] Motorola. (2001). Programming Environments Manual, For 322Bit Implementations of the PowerPC Architecture [MPCD]. [3] Motorola. (2000). MPC555P556 User Manual [MPCD]. [4] Dunlop J, Fuchs J & Mihalik S. (2001). MPC555 Interrupts [MPCD].
OS-STK-GROWTH defines stack growing direction of CPU. The stack of MPC555 is growing from high address to low address, defined as follows:
# define OS-STK- GROWTH 1 //0 means stack pointer is growing from low address to high address //1 means stack pointer is growing from high address to low address