Real Time Systems Lab: Handling Shared Resources
Real Time Systems Lab: Handling Shared Resources
Lab Manual
*CubeSat image from online article: “NASA 2024 Moon Mission Calls for CubeSats", accessed on September 10, 2021.
Dalhousie University
Department of Electrical and Computer Engineering
ECED4402 - Real-Time Systems
1 Objectives
1. Analyze and synthesize how queues are used to share data between tasks.
2. Analyze the use of mutex to share resources.
3. Develop a program to enable semaphores that trigger tasks from interrupts.
4. Analyze the use of Event Groups to synchronize between multiple tasks.
2 Equipment
3 Assessment
This lab is to be completed in teams of 2 students. A formal lab report must be handed in. The mark
breakdown is organized as follows
• Report:
– Introduction: 2 marks;
– For each exercise (10 marks);
1. Objectives
2. Answer to concluding questions
3. Critical analysis summarizing concepts and challenges
4. Demo that the system works (using video, or picture)
– Conclusions: 2 marks.
2
4 Reading Material
Before the lab, it is recommended that you become familiar with these instructions. It is also recommended
that you become familiar with the following documentation:
3
5 Lab Manipulations
5 .1 Queues
In this exercise, first you will be required to analyze the basic functionalities of queues. Second, you will be
asked to create your own application that counts and monitors the number of views on a remote server, such as
a YouTube video.
To initiate this exercise, a project can be downloaded from here. The whole project package is available.
1. Download the project, extract the files from zip folder, and open the solution with Microchip Studio.
The project is configured to use the SAMD20G18, and the FreeRTOS libraries.
2. Connect the custom board and Atmel-ICE programmer.
3. Select the SAM-ICE programmer.
1. Analyze the code. Identify how many tasks are expected to be running, and what are their roles.
Is the receiver task always in the running state? What is the role of the queue?
2. In the eventuality that the receiver task is not created, what is the content of the queue after 4 seconds?
Assume that "Sender 1" was running first. What is it after 5 seconds? To answer this question, show the
queue structure, and clearly identify the head and tail of the queue.
4
3. Build and run the code. Examine the behaviour, and explain the different messages that are observed on
the console.
4. The sender function includes a delay. Re-run the program for different delay values equal to 5 msec, 50
msec and 100 msec. Observe the effect on the output, and explain the impact on the queues. Run the
program in debug mode, and, if necessary, break it to analyze carefully the behaviour.
Concluding questions.
1. What is the data type used by the queue? Is it possible to use other data types such as floats, or strings?
Justify your answer.
2. What are the impacts of the size of the queue? Explains the benefits of increasing the size, as well as
disadvantages.
3. In the call to the xQueueSendToBack() function, explain the input parameters, and the return value.
4. In the call to the xQueueReceive() function, explain the input parameters, and the return value.
5. Why do we set the sender task priority higher than the receiver task? What states do the different tasks
enter for the different delay times on the transmit function?
Use the concepts above for the queue to create a multi-task program that will act as a YouTube server
attempting to keep track of the number of views on a video. The program will include 1 receive task acting as
the server. The primary server keeps track of how many users have accessed a specific video, and will forward
the count to the console. Also, in a network infrastructure, the sender tasks act as remote servers that provide
access to remote users. On a periodic basis, the sender tasks will define a random number of views from their
subnet that will be appended to the queue. The primary server will use the information from the queue to store
the total view count. The receiver task will display the updated total view count on each call.
The expected output is that the view counts printed to the screen is continuously increasing.
Also, to demonstrate the importance of the queue, implement a program in which the total number of user
accesses is incremented by each remote server, which then forward the message to the console. Observe the
deficiencies.
Use the increment function shown in Figure 1 which is called from the remote server task.
Hand in your code, videos of the two implementations, and a critical analysis explaining the usefulness of
queues in a real-time system.
5
void increment(int num){
int buffer = 0;
buffer = global_var;
buffer += num ;
for(int i =0; i<100000; i++);
global_var = buffer;
}
Figure 1: Primary server function to add the total counts. Note that delay artificially introduces a delay in the
function to demonstrate functionality.
6
5 .2 Mutexes
In this exercise, we will utilize Mutexes to handle data accessed by multiple tasks. Specifically, in this
exercise, we will access a shared variable through two different processes that are running asynchronously.
In the original code provided here the mutexes are disabled, and the two tasks are running at a period of
1 seconds.
2. In the main, create the mutex before starting the tasks, using: mutex = xSemaphoreCreateMutex();.
Note that the tasks should only be created, when the upon successful creation of the mutex.
3. For the lines that you want to protect in the task handler, add before: xSemaphoreTake(mutex,
portMAX_DELAY);. Also, add after those lines xSemaphoreGive(mutex);
Concluding questions.
1. By referring to the FreeRTOS documentation, explain the functionality for the xSemaphoreCreateMutex(),
xSemaphoreTake() and xSemaphoreGive() functions.
2. In general, explain how mutex avoids simultaneous access to the shared variable. Refer to Section 7.3 of
the FreeRTOS manual, and particularly to Figure 63 to justify your answer.
3. Explain priority inversion. Give a scenario in which this can occur and is detrimental to the system.
4. Explain priority inheritance. Does this help to mitigate priority inversion? If so, why?
7
5 .3 Binary Semaphores
To manage the handover between the interrupt and the task, the task ’takes’ a semaphore, and when the
interrupt is triggered, the interrupt handler (or the callback function) ’gives’ the semaphore.
In this exercise, you will use a button to trigger an event. On the rising edge of the button, the interrupt
handler will defer its functionality to the task. In this demonstration, the task will print to the host computer
console, and will toggle an LED.
To support you in this lab, the main file will be provided to you, and you will be required to complete the
code.
Download the project provided ??here. Unzip it, and open it using Microchip Studio.
1. Verify that the EXTINT library is added using the ASF Wizard.
2. Connect a button to Pin 15, and use a pull up configuration with a capacitor to enable hardware debounc-
ing. This will eliminate glitches.
4. Verify the functions to configure the input button, and to configure a callback function.
5. Verify the callback function, such that when the pin state is rising a semaphore will be given.
6. Verify the main_task handler function that prints periodically to the console at a period of one second.
7. Complete the task_led handler function with an infinite loop. In the infinite loop, first ’take’ the
semaphore.
When the semaphore is acquired, toggle the LED when the button is high, and print a message to the
console indicating how many times this task has been called.
8. In the main, call the functions to initialize the system, and enable the interrupts. Create the semaphore.
Afterwards, in the main, create the two tasks at the same level of priority, and start the scheduler.
Demonstrate using a video your functionality. Hand in your code, and include in your report an analysis of
the behaviour of this program. Explain in your analysis the usefulness of the binary semaphore for synchroniz-
ing.
8
Concluding questions.
9
5 .4 Event Groups
An event group contains a set of event bits. Each event bit can be used as a flag. In this exercise an event
group will be used to coordinate execution among several tasks.
A variable of type EventBits_t is used to determine whether the conditions to run a task are met. To
verify the conditions, the function xEventGroupWaitBits() is used. Until the conditions are met, the
task is blocked.
The conditions are updated using the functions xEventGroupSetBits(), and xEventGroupClearBits().
In this exercise, there are two buttons. Button A is used to create tasks while button B is used to delete tasks.
Each task created prints its task ID and take a varied amount of time to execute. Event groups will be utilized
to ensure each of the created tasks print in numeric order based on order of creation and runs only once after
each cycle of the main task. The code is provided to test and analyze this potential application for event groups.
The code can be downloaded from here.
3. Analyze the code and predict the output when you create new tasks.
6. Comment out the xEventGroupWaitBits() functions. Build and run. Observe the output printout
on the host computer console. What is the difference with the previous implementation?
7. Uncomment the xEventGroupWaitBits() functions. Build and run. Create several tasks using the
button then delete one task. Note that the list of tasks is no longer printed.
Create a new task using the button. Does the task ID printout on the host computer console resume?
8. Modify the code to ensure that the list of tasks can printed upon deletion.
9. Build and run your modified code. Take of a video demonstrating the modified functionality.
Concluding questions.
1. Explain how event groups are used to manage the task execution synchronization in this project. Refer to
the the Section 8.2 in the FreeRTOS manual to justify your answer. Specifically, you may use the format
in Figure 71.
10
2. Based on the original code answer the following:
(a) How does the deletion of a task affect the printing of task IDs.
(b) Explain what happens what happens when a task is added after deletion.
3. Based on the modified code with the commented out the xEventGroupWaitBits() functions an-
swer the following:
(a) How does the printing of the tasks compare to when the xEventGroupWaitBits() was uti-
lized?
4. Based on the modified code with deletion working properly answer the following:
(a) Explain how you were able to implement the fix and add comments to your updated code to explain.
(b) Submit a commented version of your updated code that handles deletion properly.
6 Conclusion
In this lab, you anyalyzed how to share resources by utilizing mutex, and queues. You also analyzed how
to synchronize using semaphores and event groups. Using these concepts, you are now equipped to program
some of your own programs to share resources, and synchronize tasks.
11
7 Appendix
If you need to re-create the project, the steps from lab 1 are summarized below:
2. Create a new Example Project. Select the project named "Quick Start for Debug Print (FreeRTOS) -
SAM D20 Xplained Pro".
This will create a project with a single task that sends a string to the debug COM port.
12