Lab 5: Real-time operating systems

Lab 5: Real-Time Operating Systems

Based on Xilinx ISE Design Suit 10.1

Department of Electrical Computer Engineering

Florida International University

Introduction

Most real-time embedded systems except for the most trivial ones need real-time operating system (RTOS) support. Different from the traditional operating systems, a RTOS is a multitasking operating system intended for guaranteeing the timeliness of the applications instead of emphasizing the throughput of the systems.

There are a number of commercial/non-commercial RTOSes available, such as VxWorks, QNX, eCos, LynxOS, and RTLinux. In this lab, we will use Xilinx Xilkernel [1] in our study. Xilkernel (as shown in Figure 1) is a small and modular kernel integrated with the Xilinx Platform Studio environment. It provides a set of core modules and POSIX style functions that can be easily customized to implement higher level of applications and services. In this lab, we will investigate a number of important mechanisms in a RTOS, i.e., thread creation, scheduling, resource sharing, and inter task communications.

This lab involves intensively on multi-thread programming. The Xilinx Xilkernel supports POSIX-style multi-threading functions. For references on functions as well as sample codes, you can check the Xilinx Xilkernel document at the EDK\doc directory or, better, check the internet. There are abundant materials there.

Figure 5-1. Xilinx Xikernel Modules [1]

Objectives

After completing this lab, you will be able to:

  • Create multiple threads
  • Use different scheduling algorithms and understand their behaviors
  • Use mutex and semaphore to guard the shared resources
  • Send and receive message among multiple processes

Acknowledgement

The original lab materials are provided by Xilinx University Program and IMEC (

Procedure

This lab comprises several steps involving RTOS study.

Open the Project Step 1

Create a lab5 folder under c:\<your directory. If you wish to continue with your completed design from lab4 then copy the contents of the lab4 folder into the lab5 folder. Launch Xilinx Platform Studio (XPS) and open the project file located in c:\<your directory>\lab5

1.Open XPS by clicking Start  Programs  Xilinx Platform Studio 10.1 Xilinx Platform Studio

2.Select Open Recent Project, Click OK and browse to C:\<your directory>\lab5

  1. Click system.xmp to open the project.
  2. Click Software > Software Platform Settings. Select the tab “Software Platform” andsetxilkernel for ppc405_0.
  3. Click “OS and Libraries” and configure xilkernel as follows.
  4. sysintc_spec : opb_intc_0
  5. stdout: RS232_Uart_1
  6. stdin: RS232_Uart_1
  7. enhanced_features: true
  8. config_debug_support: true
  9. config_bufmalloc: true
  10. mem_table: add two elements, with (mem_bsize, mem_nblks) as (4,30) and (8,20), respectively.
  11. config_msgq: true
  12. config_sema: true
  13. config_time: true
  14. config_sched: true
  15. config_pthread_support: true
  16. static_pthread_table: add one entry with (pthread_static_func, pthread_prio) as (main_prog, 0).
  17. Config_pthread_mutex: true

Figure 5-2. Software Platform Settings

  1. Click to end the OS configuration.
  2. Click “Applications” tab and select the “Set Compiler Options…” of you application.
  3. Set optimization level to be Medium. Under tab “Paths and Options”, set “Libraries to Link against” to be “xilkernel”. Click OK to confirm.

Figure 5-3. Set Compiler Options

  1. Click “Software  Generate Libraries and BSPs…” to generate the libraries and BSPs.
  2. Now you are ready to use Xilkernel in EDK.
  3. Further questions:
  4. What is RTOS? What are the differences between the RTOS with the traditional OS?
  5. What is Xilkernel ?

Multiple thread creations and schedulingStep 2

  1. Download the source code template from the course web page and unzip the source codes.
  2. Go to the “Application” tab and replace the project source with file threads_RR.c, which contains a simple program that creates four threads.
  3. Read the file “threads_RR.c”. Note that the function “main_prog” will be automatically created as configured during the kernel configurations.
  4. What is variable “taskrunning” for? Why is it defined as “volatile” type?
  5. Complete the main_prog function and create four threads using function pthread_create. For example, you can use the following code snippet tThe thread for the first function can be created as:

//start thread 1

int ret;

ret = pthread_create (&tid1, NULL, (void*)thread_func_1, NULL);

if (ret != 0) {

xil_printf ("-- ERROR (%d) launching thread_func_1...\r\n", ret);

}

else {

xil_printf ("Thread 1 launched with ID %d \r\n",tid1);

}

  1. Complete the program. Open a hyper-terminal window and download the program to the board. You should see output in the terminal window like that shown in the following Figure. Note: you might want to change the baud rate of UART IP as well as that for terminal window to 9600 to slow down the displayed messages.

Figure 5-4. The results for round robin scheduling

  1. The four threads generated in “threads_RR.c” are, by default, scheduled according to the round robin scheduling method. We will study the fixed-priority scheduling method next.
  2. How many different scheduling methods that Xilinx Xilkernel supports?
  3. To use fixed-priority scheduling method in XPS, we will have to re-configure Xilkernel a little bit. Go to “Software Platform Settings” and “OS and Libraries” tab. Set the “sched_type” under “config_sched” to be “SCHED_PRIO”. Click OK to confirm.

Figure 5-5. The results for round robin scheduling

  1. Replace the source file of the project to be “threads_PRIO.c”, which you can find in your downloaded archive. In this file, you need to complete the function main_prog such that each thread will have different priority. Assign the highest priority (1) to thread 1. The other 3 threads will get a lower priority.You can set the priority of the thread when you create it with pthread_create. You already used the pthread_create function earlier in this lab. Now, you need to change the second argument, i.e. attr, of the same function. The structure pthread_attr_tallows you to parameterize the created thread. The structure contains, amongst others, the variable sched_priority that we can use to define the priority.
  1. This is how you should proceed:
  2. Initialize the attr variable using pthread_attr_init.
  3. Assign the priority to sched_priority, which is a member of the sched_param structure.
  4. Use pthread_attr_setschedparam to assign the values of the sched_param structure to attr.
  5. Start the thread with attr as attribute using pthread_create.
  6. Compile and download the program to your board. Study the output from the hyperterminal. You find that only one thread is running. Which one? Why?
  7. To give other threads a chance to run, we need to ask the thread who always occupies the processor to release its control. A thread can go from running status to waiting status in several conditions, for example, when waiting on a timer. We can use sleep function to force a thread to give up the processor. Modify each thread function such that all threads have chances to run. Note: you might need to tune the parameters for the sleep functions in order to do so.
  8. Compile and download the program to your board and collect the results from the terminal window.
  9. Show and explain the three different sets of results shown in the hyperterminal.
  10. Further questions:
  11. How many statuses that a thread can be in Xilkernel? What are they? How do they transfer from each other?
  12. Can you implement Rate Monotonic Scheduling (RMS) scheme in Xilkernel? If yes, how? If not, why?
  13. Can you implement Earliest Deadline First (EDF) scheme in Xilkernel? If yes, how? If not, why?
MUTEX and SEMAPHORE Step 3

In this part of project, we will study how to implement mutex and semaphore to guard the shared resources and synchronize different threads.

  1. The current source code supports four running threads. As four threads use the same UART for message output, you might see that messages from some lower priority threads get interrupted. Shows a piece of output as evidence for this scenario. Again, you might need to adjust the parameters for the sleep functions.
  2. To solve this problem, we can use a mutex to ensure the exclusive access to the UART. We can create a mutex and lock this each time before the “xil_printf” function. After each xil_printf command you have to unlock the mutex.
  3. In order to use mutex, you need to first initialize the mutex with function pthread_mutex_init. Then you can lock and unlock the mutex with pthread_mutex_lock and pthread_mutex_unlock.
  4. Add a mutex in your current source code to ensure the exclusive usage of UART. Compile and download the program to the board.
  5. Show the correctness of your programs with discussions of the outputs from the terminal window.
  6. One problem for priority scheduling with shared resources is the priority inversion. Explain what the “priority inversion” is. How can you tell if and when a priority inversion scenario occurred in your experiment?
  1. We next study the usage of semaphore. Replace the current source file to sama.c, which you can find in your downloaded archive.
  2. The file sama.c implement an application that spawns two threads, i.e., print_odd and print_even. The sample output is as follows.

To print out the message correctly, the two threads need to be synchronized appropriately. We can do this as what shown in the following figure.

Figure 5-6. Synchronizing two threads

This is how it works. The print_odd thread will post the semaphore odd_done when it finishes. The print_even thread will wait on this odd_done semaphore to continue. When print_even has completed, it posts the semaphore even_done, which is waited by print_odd thread. In the given template, weneed to add proper synchronization functions, including initialization (“sem_init”), post (“sem_post”), and wait (“sem_wait”) functions for semaphores.

  1. Compile the code and download the program to the board. Study the output message from the terminal.
  2. In the code, the UART is guarded with a mutex. If you remove this mutex, will the program print the message correctly? Why or why not? Update the program to verify your conclusions.
  3. What are the difference between the mutex and the semaphore?
Inter-task Communication Step 4

In this part of lab, we will study how different threads can communicate with each other using message passing strategy.

  1. Replace the source file for current project to msg.c, which you can find in your downloaded archive.If you look at the code you can see two threads: producer and consumer, which communicate with each other using message queue. The producer generates a number and a character and stores it in the data structure prod_msg. Then it prints the generated data and sends the data to the message queue. The consumer thread waits on the messages from the producer. When message received, it prints the message to the terminal. Here is the sample output.

Figure 5-7. Sample outputs for IPC

Note that, even though both producer and consumer “share” the same message queue, you do not have to use a semaphore explicitly here to synchronize the sending and receiving operation. You may need to use a mutex as before for the UART, though.

  1. To use the message queue, you need to create the message queue (using msgget) and then send (using msgsnd) or receive (using msgrcv).
  2. Complete the source code. Compile and download the program to the board to verify your results.
  3. Further questions
  4. Besides message passing, what else method can two processes adopt to communicate with each other? What are the advantages and disadvantages of each method?
  5. In message passing, the communication can be blocking or non-blocking. Explain their differences.

Conclusions

In this lab, we have studied a number of critical concepts and functions in dealing with multiple processes/threads for embedded systems. These functions are usually supported in RTOS to reduce the design cost. Specifically, we examined how to create a thread, prioritize a thread, schedule multiple threads, use mutex/semaphore to protect the shared sources and synchronize thread executions, and use message queue to communicate among multiple threads. You have practiced on how to write C programs for a multi-threading environment.

What to hand in …

  1. Answer questions listed in the lab instructions.
  2. Your C codes and representative terminal outputs that can demonstrate that your codes work properly.
  3. Discuss problems you solved and summarize experiences you gained from this lab.

References

  1. Xilnix Xilkernel,
  2. Multi-threading with POSIX threads in google.com,
  3. Threads programming,

1