An operating system designed to use specifically in real-time systems. RTOS consists of following main components in terms of management and synchronization:
- Scheduler
- Communication Mechanisms
- Critical Region Mechanisms
- Memory Management
- Timing Services
- Peripheral Drivers
- Protocol Stack
- File System
- Device Management
The scheduler is the part of the kernel responsible for deciding which task should be executing at any particular time. The kernel can suspend and later resume a task many times during the task lifetime.
The scheduling policy is the algorithm used by the scheduler to decide which task to execute at any point in time.
- Run-to-Complete
- Time Slicing
- Round Robin
- Priority
- Preemptive
- Non-Prememptive
There are several types of synchronization primitives in an RTOS to be used according the requirements. These primitives are named as following:
- Mutex
- Semaphore
- Queue
Although concept is the same but these constructs vary in implementation for different real-time operating systems.
A program object that is created so that multiple program thread can take turns sharing the same resource
Semaphore is simply a variable which is non-negative and shared between threads. This variable is used to solve the critical section problem and to achieve process synchronization in the multiprocessing environment
Refer to Task C for an implementation perspective.
A queue is a FIFO (First In First Out) type buffer where data is written to the end (tail) of the queue and removed from the front (head) of the queue. It is also possible to write to the front of a queue.
Refer to Task D for an implementation perspective.
Import RTOS project from the the link. Run the code in proc.c and understand initialization of processes in MBed OS.
Run the code in syncProc.c and observe the difference in output.
Refer to cod in sem.c.
Button interrupt releases the semaphore \texttt{blink} is waiting for, and allow it to blink a specified number of times. THe \texttt{blink} turns back to wait again.
Run the queue.c code to observe semaphores in implementation.
Button interrupts increments a count and send the value over queue. The blink recieves value and blinks LED as many times as specified. Then blink goes back to wait for next message from queue.
Instantiate the ball and background processes as threads while button interrupts as a rising edge interrupt. Run the code and try to play the game. Are you satisfied with the synchronization of graphics? Try to improve it.
You can find the code snippets in rtos1.c.
void btn_int()
{
bounce_up = 1;
}
void ball_thread()
{
led1 = 1;
// set font
BSP_LCD_SetFont(&Font20);
// set LCD background to white
lcd.Clear(LCD_COLOR_WHITE);
lcd.SetBackColor(LCD_COLOR_WHITE);
// initial state of ball
y_movement = 0;
bool bounce_down = 0;
while(1)
{
if (x_movement >= 220 && y_movement <= 70) // collision!
{
// Prompte the end of the game.
lcd.Clear(LCD_COLOR_WHITE);
lcd.DisplayStringAt(0, LINE(1), (uint8_t *)"GAME OVER", CENTER_MODE);
// reset positions.
x_movement = 0;
y_movement = 0;
bounce_up = 0;
bounce_down = 0;
Thread::wait(5000);
}
else if (bounce_up) // ball going up
{
lcd.SetTextColor(LCD_COLOR_RED);
lcd.FillCircle(20+y_movement, 40, 20);
y_movement += 3;
if (y_movement >= 120) // the highest ball can go.
{
bounce_up = 0;
bounce_down = 1;
}
Thread::wait(250);
}
else if (bounce_down) // ball going down
{
lcd.SetTextColor(LCD_COLOR_RED);
lcd.FillCircle(20+y_movement, 40, 20);
y_movement -= 5;
if (y_movement <= 0) // touching the ground.
bounce_down = 0;
Thread::wait(250);
}
else // default position of the ball
{
lcd.Clear(LCD_COLOR_WHITE);
lcd.SetBackColor(LCD_COLOR_WHITE);
lcd.SetTextColor(LCD_COLOR_RED);
lcd.FillCircle(20, 40, 20);
Thread::wait(250);
}
}
}
void bg_thread()
{
// color and shape of obstacle.
lcd.SetTextColor(LCD_COLOR_BLACK);
lcd.FillTriangle(0, 75, 0, 250, 275, 300);
// initial position
x_movement = 0;
while (1)
{
if (x_movement >= 250) // the obstacle is through.
x_movement = 0;
// obstacle approaching.
lcd.Clear(LCD_COLOR_WHITE);
lcd.SetTextColor(LCD_COLOR_BLACK);
lcd.FillTriangle(0,75,0,250-x_movement, 275-x_movement, 300-x_movement);
x_movement += 5;
Thread::wait(250);
}
}
Improve the bounce game from last lab using synchronization primitives observed here such that graphics are more aligned this time. Following hints might help:
- Use a separate thread to manage LCD resource.
- Pass position arguments for ball and obstacle to thread responsible for LCD resource.
- This thread-to-thread communication can be achieved through queues.
- Use semaphores to avoid unaligned execution of threads.
The official documentation of semaphors and queues might help.