You are on page 1of 9

ECE3073 Computer Systems

Real Time Systems Lab 1 Concurrent Tasks


Lindsay Kleeman, Monash University, Dept ECSEng.

0 Aims

To implement concurrent tasks using the uC/OS-II real time kernel running on the NIOS
II processor.

Understand and measure the overhead in running a timer interrupt in a real time kernel.

Display the processor utilization, current time in hours minutes and seconds, and a
graduated LED brightness using pulse width modulation.

1 Equipment
DE2 board.
Quartus/Nios II development software containing the uC/OS-II real time kernel.

2 Preliminary Work
Print and read this document and bring it to the lab. During the lab, ensure you write answers

markers. Where you see a


ask your demonstrator to initial your sheet
next to these
in the lab to indicate you have answered the questions correctly and demonstrated your work.
Read the documentation (and attend lectures) on the statistic task OSStatInit() on the unit
web page in the resources section in the documentation uC/OS-II Real Time Kernel
Reference Manual. Your demonstrator will ask you questions about this in the lab.
Write the software for section 3.6 before the lab. You will test this during the lab. The lab
should take two lab sessions to complete.

3 Method
3.1 Hardware Definition
Download and install the Quartus project available on the unit website as a Quartus Archive
File by double clicking the file with extension .qar - Quartus should run and ask where to
install the project. A static RAM SOPC module needs to be installed separately as follows:
Download the ZIP file static_ram.zip from the unit webpage lab section. Ensure that SOPC
is not running and then unzip the static RAM SOPC module into your project directory. You
should be able to see a new folder named static_ram in your project directory now. If you
now run SOPC from Quartus and open the RTSLab1.sopc file, the following modules should
be available:

NIOS II/f 32 bit RISC processor


JTAG UART
Tri_state_bridge (needed for the Static RAM)
Static RAM
7 bit PIO interfaces to all eight 7 segment displays
8 bit PIO interface to the 8 green LEDs LEDG0-7.
4 bit PIO interface to the 4 push buttons Key[3:0].
LCD lcd_16207_0 display interface.
Interval timer with a 10 msec simple period interrupt

You must upgrade the SRAM module as follows: In the Component Library window on the
left hand side of SOPC, click on the + next to DE2 Board and right click on the Static RAM
and upgrade, accepting the default values. Right click on the static_ram_0 in the Module list
of SOPC (main window) and Replace with version 1.01. Unfortunately this procedure
must be followed every time SOPC is opened. If you fail to do this you will end up with
unknown port errors in the Quartus compilation.
This hardware configuration will be the basis for the real time laboratories.
Generate the SOPC system (bottom right button of SOPC screen), then compile the Quartus
project, and download the hardware configuration to the DE2 board.

3.2 Software Project Definition


Run NiosII IDE as follows: from the START menu of the computer, under Alter -> NiosII
EDS10.1sp1 -> Legacy NiosII Tools -> NiosII 10.1IDE.
From the Integrated Development Environment (IDE) use the file menu-> New Project ->
Nios II c/C++ Application
Select the Hello MicroC/OS-II project template and the SOPC Builder PTF file from your
project menu (see the dialogue box below for an example) and click Finish.

The IDE should look like the following screen shot. To compile the hello_ucosii.c program,
Build All (click on the 010 button or use Project Menu-> build all).

Once the compiler has finished with no errors, you can run the program. Ensure that you
have first downloaded the processor configuration from Quartus.
To run the program, use the run -> Run menu or the green circle with white triangle tool,
and select Nios II Hardware-> hello_uscosii_0 as shown below:

Click Run and the program should download and run. If you receive a communication error
here, ensure that you have first downloaded the processor configuration from Quartus. This
error can also occur if no clock is connected to the processor in Quartus or there are no pin
assignments in the Quartus project.
You should observe that there are two tasks running from the console messages.
Which task runs at the higher priority?

This symbol means write your answer here!

Change the priority of task1 to match task2 in the OSTaskCreateExt() kernel call.
Run the modified code. Document your findings and then restore the original priorities.

Can two tasks share the same priority in uC/OS-II? Try it! Hint: modify the demonstration
code to check the error codes returned when call kernel functions such as OSTaskCreateExt.
This can be done as follows:
int error_code;
error_code = OSTaskCreateExt( task1, etc.);
if (error_code != 0) printf(Error creating task1 with error code %d\n, error_code);
You can look up the error codes by opening the includes.h file by double clicking on this
filename in the Outline window on the right hand side, and then double clicking on the
ucos_ii.h file from the Outline window again once includes.h is opened. You will notice that
all the #define symbols defined in the header file opened are listed in this Outline window.
Click on some of the OS_ERR_... ones.
Can two tasks share the same priority in uC/OS-II?

Do you think other real time kernels can run two tasks with the same priority?

Why does each task contain an infinite loop?

Identify the time delay call to the kernel in each task. What is its purpose? Look up the
function in the uC/OS-II Real Time Kernel Reference Manual on the unit website under the
resources section. Leave this open for the rest of the lab so you can check what each kernel
function does and its error codes.
Change the delay in task2 to 10 seconds and test the change.

Remove the time delay call in the lower priority task loop comment it out using // at the
beginning of the line. Does the higher priority task still run? (Hint: Reduce the delay in the
higher priority task to 10 msec and simplify the output from the lower priority task to one .
to help decipher all the output).

Restore the previously commented line of code and now comment out the delay call in the
higher priority task. What happens now when you run the code?

Explain your findings to the demonstrator and get all the previous answers checked.

3.3 Statistics Task


The uC/OS-II kernel has a statistic task that reports on the idle time of the system that is
what percentage of time the lowest priority idle task runs. In order for this to be reported
correctly, the OSStatInit() (have you looked it up in the reference guide??) call must be made
with just one1 (ie the current) task running. A counter is incremented for one second to
measure the no load number of increments that the processor performs. This value is stored
in the global variable called OSIdleCtrMax. We will use this later as a measure of the
overhead in the timer interrupt of the real time kernel. Once other tasks are created the idle
task continues to measure its time every second by using the same increment of the counter.
You can access the percentage utilization of the real time system by reading the global
variable OSCPUUsage.
Rearrange the OSTaskCreateExt() calls so that you satisfy the requirement for one current
task running when you call OSStatInit(). Display the OSCPUUsage as two decimal digits on
the two left most 7 segment displays. Show your demonstrator.

3.4 Timer Interrupt Overhead


Arrange to printf your value of OSIdleCtrMax after the OSStatInit() call. Test it and record
the value which we will call IdleCountWith100_ISRs. OSIdleCtrMax is a 32 bit integer and
you should use the long int format in printf(OSIdleCtrMax is %ld, OSIdleCtrMax). Note
that the number of idle counts represents one second minus 100 executions of the timer
Interrupt Service Routine (ISR) since the timer interrupt occurs every 10 msec.

IdleCountWith100_ISRs =

Exit the NIOS IDE.


Change the timer interrupt time to 1 msec and reconfigure the hardware (using SOPC2 and
run generate, re-compiling Quartus and downloading the new configuration to your board
from Quartus). What is the new value of OSIdleCtrMax? Note that this
IdleCountWith1000_ISRs represents one second minus 1000 executions of the timer ISR. So
the difference of the two values represents 900 ISR executions.

IdleCountWith1000_ISRs =
Estimate the percentage execution overhead for a 1 msec timer interrupt. To do this first
work out how many IdleCount increments would occur for just one ISR and call it ISRinc.
Hint: you should realise that this is the difference/900. Now how many idle counts would
occur in a full second without any ISRs running? (Hint: add 100* ISRinc to
IdleCountWith100_ISRs). The % overhead with a 1 msec timer interrupt is then
1000*ISRinc/ (idle counts in a full second) * 100. Write your answer here:
1
2

After OSStatInit() has returned, further tasks are usually created to implement the system.
If you restart SOPC, you may need to upgrade the SRAM module again as described above in section 3.1

% overhead 1 msec timer =

3.5 Time of Day Clock


The processor used in this lab is a NIOS II/f which includes cache memory for higher
performance. You need to access PIOs in this section and if this is done via memory pointers,
there can be issues related to the cache intercepting the read/write operations and delaying the
transactions to actual IO devices. However using the macros:
IOWR(base_address, offset, data);
data = IORD(base_address, offset);
compiles into stwio and ldwio assembly language instructions that bypass the cache. You
should use IORD and IOWR in this and the next lab to avoid cache issues.
Rewrite the code in task1 to perform a simple clock output to the 7 segment display in
seconds minutes and hours use just one task here! Ensure your timer is still set to 1 msec
for this section as it should be after completing the previous section. You should use the
OSTimeDlyHMSM() kernel function call. Is this always going to be accurate?

What if the clock update was given to a lower priority task and a higher priority task used a
high percentage of the processor time? Can you demonstrate your answer by using a couple
of nested for loops in a higher priority task to burn CPU cycles. (The high priority task must
still contained a delay call).

Show your clock to the demonstrator.

3.6 Modulated LED Output


Create a new task that will output different brightness levels for a LED. This can be achieved
by using a pulse width modulation scheme based on the system timer. Here is a possible way
to achieve this. Suppose we store a brightness level from 0 to 32 in an INT8U type variable
(unsigned 8 bit integer type defined by uC/OS-II):
INT8U brightness = 16, accumulator=0;
while (1)
{

accumulator += brightness;
if (accumulator >= 32)
{
/* output a 1 to the LED here */
accumulator -= 32; /* take off the 32 corresponding to a 1 LED output */
} else
{
/* output a 0 to the LED here */
..
}
OSTimeDly(1); // delay a timer tick and give other tasks a chance to run
} // while (1)
Implement this algorithm and vary the brightness of the LED from off to full in a linear ramp
upwards and then downwards once every 10 seconds (that is in a triangular wave pattern).
Note the idle time of the real time system now. Show your demonstrator.

3.7 Wave Pattern LED Output


Extend this to a circulating wave pattern on 8 LEDs you should use function calls in your
code here! A movie is available on the unit website. You must use a moving triangular wave
pattern (not a saw tooth) where a complete wavelength corresponds to the 8 LEDs. Note the
idle time and show off your presentation skills to the demonstrator!

4 Conclusions
This lab has introduced the real time kernel uC/OS-II and you should understand the fixed
priority scheduling, task creation and delay kernel functions. The overhead in using a real
time kernel timer interrupt should have been noted as only a few percent of execution time in
the lab results.
The work in this lab will be applied to later labs in the design and implementation of a simple
alarm clock, where the alarm will consist of a wave pattern of LEDs. We will introduce
inter-process communication mechanisms in these later labs.

You might also like