HKUST COMP355 Project Report of a Small Real Time Operating System – USTOS - 1 - HKUST COMP355 Embedded Systems Software Project Report of a Small Real Time Operating System – USTOS Instructor: Prof. Jogesh K. Muppala Student Name: XIAO, Jianxiong Student Email: [email protected]Student ID: 05556262 Abstract: This report describes the details about the design and implementation of a small real time operating system USTOS. Its major point focuses on explaining the context switching by tricky usage of stack and synchronization mechanism. Keywords: RTOS, Context switch, 8051, C51, Synchronization mechanism 1. Introduction 1.1 Project Introduction It is a trend that RTOS is used more and more in the embedded systems. In today’s market of RTOS, uC/OS, VxWork are two most popular ones among them. While at the same time, there is large percentage of embedded system market for 8051 series microcontroller. Up to now, 8051 series microcontroller is still the most popular MCU all around the world. Because of the important role that 8051 series MCU are playing, some researchers and engineers have been trying to develop or transplant RTOS that can be run on it. Keil, the manufacture of the most famous and popular C compiler for 8051, develop one RTOS called RTX51 Real-Time Kernel. But the ROM space needed for RTX51 is more than 6K which is pretty large comparing with the 4K ROM in 80C51 and 8K Flash ROM in 89S52 etc. RTX51 also need the 8051 MCU to have foreign RAM to save data. Of course, Keil also offer another solution called RTX Tiny which needs only 0.9K footprint in ROM. However, RTX Tiny does not support priority based scheduling and interrupt manage. At the same time, both of RTX51 and RTX51Tiny do not offer any source code which is impossible for the application program developers to modify them according to their special requirement. Lots of embedded engineers are trying to transplant the existing open-source RTOS into 8051 MCU. But because of the lack of RAM and low speed of 8051 serious MCU, there are many difficulties and too high footprint to want to port most of RTOS into 8051 MCU. uC/OS, the most popular RTOS around the world, is ported on 8051 successfully. But because of its large footprint and its requirement that all functions should be reentrant functions, it is not suitable enough for real application.
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
HKUST COMP355 Project Report of a Small Real Time Operating System – USTOS
- 1 -
HKUST COMP355 Embedded Systems Software
Project Report of a Small Real Time Operating System – USTOS
#define OS_EXIT_CRITICAL() if (--Os_Enter_Sum==0) Enable_Interrupt()
But why do we need the variable Os_Enter_Sum to record the levels of Critical Section the
CPU enter? This is used to solve the potential problem that is mentioned at the bottom of Page
99 of the reference book [1]. A simple example to illustrate the problem by just using
en/disable interrupt mechanism for critical sections is like this:
void function_A()
{ Disable_Interrupt();
� Interrupt is disabled
function_B();
� Interrupt is enabled!!!! ERROR!!!!
Enable_Interrupt();
}
HKUST COMP355 Project Report of a Small Real Time Operating System – USTOS
- 8 -
void function_B()
{
Disable_Interrupt ();
…… � Interrupt is disabled
Enable_Interrupt();
� Interrupt is enabled
}
2.7 Timing Service
USTOS provides the timing service by the API “void OS_TaskDelay(uint8 nTicks)void OS_TaskDelay(uint8 nTicks)void OS_TaskDelay(uint8 nTicks)void OS_TaskDelay(uint8 nTicks)” which will
delay the called task but nTicks numbers of Ticks. The unit of nTicks, Tick, includes
OS_CONFIG_TICKS_CNT numbers of happening of OSTimer0_ISR(). This mechanism is to
prevent too frequent calling the OS_TimeTick() functions which may waste lots of time, i.e., to
slow down the timer in case you do not need it to run so quickly.
HKUST COMP355 Project Report of a Small Real Time Operating System – USTOS
- 9 -
if ( OS_RemainTick[i]!=0 )
{ OS_RemainTick[i]--;
if(OS_RemainTick[i]==0)
OS_TaskStatus = OS_TaskStatus | (0x01<<i);
}
}
}
OS_TimeTick(void)OS_TimeTick(void)OS_TimeTick(void)OS_TimeTick(void) is used to awake the sleeping blocked tasks if the time for them to wake up
arrives. It reduces the count in the OS_RemainTick[] array and check whether it is equal to zero.
If yes, it will change the state of the that task into ready state.
API function “void OS_TaskDelay(uint8 nTicks)void OS_TaskDelay(uint8 nTicks)void OS_TaskDelay(uint8 nTicks)void OS_TaskDelay(uint8 nTicks)” is used to set the remaining time in the
OS_RemainTick[] array and change the running task into ready state. You may see that this
function in fact is a reentrant function since nTicks is a local variable and other parts are
embraced by critical section protection mechanism. Why it is written like this way? I will
explain it in Section 2.8.
2.8 Basic Principles of Synchronization Mechanisms
All the synchronization includes three parts:
1. Create: which performs some initialization of the RAM where storages the information.
2. Receive: which may cause the task to wait for some condition and become block.
3. Send: which may cause the condition that other task is waiting for to become true and
let that task to be available to run.
The pseudo-code of the major skeleton framework is shown here.
Receive(Data_Pointer address, …)
{
OS_ENTER_CRITICAL();
if (not need to block � what you need already exist)
{
//handling the return value and maintain structure
You may need some time to read this pseudo-code and to figure out the mechanism of this
common framework. With this skeleton code, all codes for semaphore etc become very simple.
A special tricky part that needs more attention is the OSIntNesting problem. As we know, the
OS cannot block the ISR routine or perform context switching before return back from the ISR.
Be precisely, David E. Simon points out two rules that an ISR must obeys on Page 199 of the
reference book [2]:
Rule 1: An interrupt routine must not call any RTOS function that might block the caller.
Rule 2: An interrupt routine must not call any RTOS function that might cause the RTOS to
switch tasks unless the RTOS knows that an interrupt routine, and not a task is executing.
And since every ISR will call OS_INT_ENTER() which will let OS knows that now Send()
function is called by ISR or Tasks. The OS then can judge from this to know whether to
perform context switching or not.
Another place that needs to pay attention is the addressing of the data for synchronization, such
as the place to save the semaphore, mailbox, or message queue. I have mentioned in Section
2.1 that USTOS uses static memory allocation. So the application programmer will define a
place to put the data and pass an address pointer to the Receive() and Send() function. There is
HKUST COMP355 Project Report of a Small Real Time Operating System – USTOS
- 11 -
not explicitly mapping between task ID and the data used for synchronization such as
semaphores. And example of this is shown here.
Mailbox_t Mailbox1;
OS_MailboxCreate(0,&Mailbox1);
OS_MailboxSend(&Mailbox1,0x1234);
OS_MailboxReceive(&Mailbox1,&rcvMsg);
As I mention is Section 2.7, the API function “void OS_TaskDelay(uint8 nTicks)void OS_TaskDelay(uint8 nTicks)void OS_TaskDelay(uint8 nTicks)void OS_TaskDelay(uint8 nTicks)” is much like
the Receive() function here, which may cause the task to wait for some condition and become
block. So the major skeleton is the same useful for the function “void OS_TaskDelay(uint8 void OS_TaskDelay(uint8 void OS_TaskDelay(uint8 void OS_TaskDelay(uint8
nTinTinTinTicks)cks)cks)cks)”.
2.9 Binary Semaphore
Binary semaphore is the most simple synchronization mechanism in USTOS. At the same time,
it is also the most efficient one in USTOS. It will cost only 1 Byte RAM.
The usage example:
BinSem_t BinSem1;
OS_BinSemCreate(&BinSem1);
OS_BinSemV(&BinSem1);
OS_BinSemP(&BinSem1);
Let me elaborate the details about the implementation of the binary semaphore. The type
definition of binary semaphore is here:
typedef uint8 BinSem_t;
One bit of the semaphore is used by indicating whether the corresponding task is waiting for
that semaphore or not. If yes, the corresponding bit will be set to 1. Since the Idle Task will not
try to get the semaphore, so the most significant bit which is corresponding to the idle task is
used to indicate the value of the semaphore. The other things are similar as the skeleton code.
HKUST COMP355 Project Report of a Small Real Time Operating System – USTOS
- 19 -
OS_MailboxSend(&Mailbox1,0x5678);
OS_INT_EXIT();
}
#pragma disable
void myISR2(void) interrupt 2
{ OS_INT_ENTER();
OS_MsgQPost(MsgQ1,P1);
OS_INT_EXIT();
}
void Task0(void)
{ uint16 rcvMsg;
while(1)
{ OS_MailboxReceive(&Mailbox1,&rcvMsg);
P1=rcvMsg/256;
P0=rcvMsg%256;
}
}
void Task1(void)
{ uint8 myflag=1;
while(1)
{
if(myflag)
{ myflag=0;
OS_MailboxSend(&Mailbox1,0x1234);
}else
{ OS_BinSemP(&BinSem1);
OS_BinSemP(&BinSem1);
OS_TaskDelay(1);
}
}
}
void Task2(void)
{ uint8 Msg2;
while(1)
{ OS_MsgQPend(MsgQ1,&Msg2);
OS_BinSemV(&BinSem1);
}
}
void main(void)
{ OSInit();
OS_MailboxCreate(0,&Mailbox1);
OS_BinSemCreate(&BinSem1);
OS_MsgQCreate(2,MsgQ1,4);
PX0=0; IT0=1; PX1=1; IT1=1; //Extern Interrupt
TMOD = (TMOD & 0XF0) | 0X01; //System Timer Setup
TH0 = 0x0; TL0 = 0x0; //Time interval = 0xFFFF
TR0 = 1;
ET0 = 1;
PT0 = 1;
HKUST COMP355 Project Report of a Small Real Time Operating System – USTOS
- 20 -
OSStart();
}
4. Hardware/software Requirements
4.1 Hardware
I choose Intel 8051 microcontroller as the hardware platform in this project. This is because it
is cheap, and slow. Slow speed means that the resource is really limited and the main characteristics of embedded system are shown most explicitly. So it is a good time to practice
the principles of embedded system. The big picture of the architecture of 8051 MCU is like the
following (It is from the reference [6]). If you need further information, you are encouraged to
read the materials in the reference [6].
4.2 Software
The tool chain that I plan to use is like following:
• Cross-compiler: Small Device C Compiler.
• Simulator: 8051 Microcontroller Series Simulator
• Cross-compiler: KeilC51 Compiler IDE
• Downloader: AT89S PC Based Programmer
HKUST COMP355 Project Report of a Small Real Time Operating System – USTOS
- 21 -
But after trying all of them, I found that the SDCC compiler and the 8051 Microcontroller
Series Simulator are too weak in functionality and difficult and inefficient for coding and
debugging. While at the same time, Keil C51 complier together with uVision IDE, the most
popular developing environment around the world for 8051, offers an excellent programming
& debugging environment, as well as very precise simulator. Please notice that Keil C51
compiler is NOT free software. But you may get an evaluation edition at the Keil’s Website:
http://www.keil.com/demo/. Since the special characteristic of this compiler, I cannot
guarantee USTOS can be compiled successfully on all the versions of the compiler. The
version of my complier and simulator are Keil C51 V7.50 and uVision V2.40. The target MCU
is the most popular 8051 series MCU -- Atmel AT89S52.
A real world RTOS is not just to be used by one hardware platform. So I planed to divide the
USTOS into two separate parts. One is hardware platform independent part which is all written
in C language. The other is hardware dependent part written in both C and assembly language.
But when I was implementing, I realize that I almost do not need any assembly language at all
since Keil C51 compiler have all kinds of functions to help. And at the same time, the USTOS
V1.0 makes use of lots of characteristic of Keil C51 compiler and 8051 hardware architecture
in order to speed up and save RAM. So it is very difficult and inefficient in run time if I divide
USTOS into two separate parts by brute force.
And since there is no packet support package for 8051 series microcontroller, I start all my
codes from scratch under the help of some description about the hardware architecture of 8051
series microcontroller.
4. 3 Compiler Setup Keil C51 Compiler has 10 levels of optimization. Each higher optimization level contains all of the characteristics of the preceding lower optimization level. USTOS supports Level 0 to Level 7 optimization. Please read the reference [7] for more details. Level 0
Constant Folding: The compiler performs calculations that reduce expressions to numeric constants, where possible.This includes calculations of run-time addresses. Simple Access Optimizing: The compiler optimizes access of internal data and bit addresses in the 8051 system. Jump Optimizing: The compiler always extends jumps to the final target. Jumps to jumps are deleted.
Level 1 Dead Code Elimination: Unused code fragments and artifacts are eliminated. Jump Negation: Conditional jumps are closely examined to see if they can be streamlined or eliminated by the inversion of the test logic.
Level 2
HKUST COMP355 Project Report of a Small Real Time Operating System – USTOS
- 22 -
Data Overlaying: Data and bit segments suitable for static overlay are identified and internally marked. The BL51 Linker/Locator has the capability, through global data flow analysis, of selecting segments which can then be overlaid.
Level 3 Peephole Optimizing: Redundant MOV instructions are removed. This includes unnecessary loading of objects from the memory as well as load operations with constants. Complex operations are replaced by simple operations when memory space or execution time can be saved.
Level 4 Register Variables: Automatic variables and function arguments are located in registers when possible. Reservation of data memory for these variables is omitted. Extended Access Optimizing: Variables from the IDATA, XDATA, PDATA and CODE areas are directly included in operations. The use of intermediate registers is not necessary most of the time. Local Common Sub expression Elimination: If the same calculations are performed repetitively in an expression, the result of the first calculation is saved and used further whenever possible. Superfluous calculations are eliminated from the code. Case/Switch Optimizing: Code involving switch and case statements is optimized as jump tables or jump strings.
Level 5 Global Common Sub expression Elimination: Identical sub expressions within a function are calculated only once when possible. The intermediate result is stored in a register and used instead of a new calculation. Simple Loop Optimizing: Program loops that fill a memory range with a constant are converted and optimized.
Level 6 Loop Rotation: Program loops are rotated if the resulting program code is faster and more efficient.
Level 7 Extended Index Access Optimizing: Uses the DPTR for register variables where appropriate. Pointer and array access are optimized for both execution speed and code size.
HKUST COMP355 Project Report of a Small Real Time Operating System – USTOS
- 23 -
5. Conclusions
5.1 Summary
This project is challenging as an undergraduate course’s project within such short period of
time. But through this project, I know the principles of the embedded system software more
deeply and USTOS will be a small enough OS for other beginner to read and learn.
5.2 Future Work
Because this is just a UG course project and not a research project, no new scheduling method
is invented. And thus it emphasizes the implementation but not the creativity. If it is good to
have new scheduling algorithm, I will add it to USTOS.
Another possible improvement is to implement the Priority Inheritance Protocol to solve to
Priority Inversion Problem in USTOS.
Some other possible development may contain transplanting USTOS into other hardware.
Nevertheless, USTOS will be an open-source RTOS for anyone to use and study. Hopefully
my work can be used by industry or by education.
6. References
[1] Jogesh K. Muppala, HKUST COMP355 Embedded System Software Lecture Notes and