Blog 2

 RTOS Demo codes

   In this blog, I will explore the purpose and functionality of the provided RTOS demo codes.

What is RTOS



RTOS represents for 'Real Time Operating System'.

Operating System (OS) is a piece of codes that runs other piece of codes.

RTOS works as the diagram showing above, it looks as multiple while loops working at the same time. But the truth is the time interval between each task is too small, so as the former task is finished the later one is also ready to be finished. 

RTOS Demo 1:


The RTOS is configured with a 100 ms minor cycle, and four tasks are defined with rates of 1000 ms, 500 ms, and 100 ms (for the remaining two tasks). Once rtos_run() is called in main(), the scheduler repeatedly executes each task according to its specified period. Each task outputs a short identifier (1, 2!, 3, and 4) through the serial port, allowing the user to observe how tasks with different timing intervals are interleaved and managed by the RTOS.

The number of tasks 3 and 4 is much greater than that of tasks 1 and 2 because the rate of tasks 3 and 4 is 100ms (meaning it can print 10 times per second). If I set the rate of tasks 1, 2, 3, and 4 to the same 100ms and each task outputs the corresponding T.


We can find that the messages T1, T2, T3, and T4 appear repeatedly in sequence, indicating that the scheduler is cyclically invoking each task according to its defined timing parameters.



RTOS Demo 2:

The RTOS creates three tasks with different periods: executing every 1000ms, 500ms, and 100ms respectively, and outputting information via serial port.  Task1 increments a counter every time it executes, and when the counter reaches 5, rtos_terminate() is called to terminate the scheduler. After the RTOS terminates, the program returns to main, prints  messages ('RTOS has been terminated').


I found that this programme ended when it repeated 5 times because the 'rtos_terminate ( )' if counter reaches 5.


If I want  to restart the loop we can use 'while(True)'or 'while(1)' and 'counter=0' to reset the counter, it will restart again.




We can see that it restarts correctly.

RTOS Demo 3:


In this Demo code , we can see there are three tasks (1000 ms, 500 ms, and 100 ms).
The variable counter is used to dynamically control Task 3 (the 100 ms task). When counter == 2, Task 1 disables Task 3 using rtos_disable (The_third_rtos_task). Task 2 increments counter each time it runs, and when it reaches 5, it resets counter to 0 and re-enables Task 3 using rtos_enable(The_third_rtos_task). In main(), the counter is initialized and the scheduler is started with rtos_run().





To revise the code, I add two more tasks (Task 4 and Task 5)



Then I compile and run the demo again. The result is shown below:





RTOS Demo 4:

In this demo code, two periodic tasks are defined (1000 ms and 500 ms), and each task is assigned a 2-byte message queue using queue=2.

Task 2 (500 ms task) sends the current value of count to Task 1 using rtos_msg_send(). When Task 1 detects that a message is available (checked using rtos_msg_poll()), it reads the message with rtos_msg_read(), prints it, then sends the updated count value back to Task 2 and increments count.

Similarly, Task 2 checks its own queue, reads any received message, prints it, and increments count. The result is shown below:




I also revise this code by changing 'if' to 'while' to empty the queue at once to prevent messages from piling up.



I also add 'if' because Task2 (500ms) sends data faster than Task1 (1000ms) reads data, the queue only has 2 bytes, which can easily fill up. 


And here is the result:



RTOS Demo 5:

In this program, the first task runs every 1000 ms, continuously incrementing a counter within a loop. Each time the counter increments, its value is sent to the second task using the rtos_msg_send() function, while the rtos_yield() function allows the scheduler to switch contexts. The second task runs every 500 ms, checking for messages using the rtos_msg_poll() function. If a message is available, its value is read using the rtos_msg_read() function and printed to the serial terminal. The queue=2 parameter allocates a small message buffer for inter-task communication.


From the image we can see that  every time task 1 counts, then task2  sends '' count is : ..''.
It illustrates how the RTOS  enables  data transfer between scheduled tasks.

RTOS Demo 6:

In this programme, we can see how RTOS codes control LCD display sequence.

In the code, two tasks run at the same period (1000 ms), but both must call rtos_wait(sem) before using the resource and rtos_signal(sem) after finishing. Since the semaphore sem is initialized to 1, only one task can access the LCD at a time. While one task is displaying its messages in a loop, the other task must wait until the semaphore is released. 

Task 1 shows 'red on/off' every 1000ms




Task2 shows 'red on/off' every 200ms


This prevents both tasks from writing to the LCD simultaneously, ensuring mutual exclusion and proper synchronization between tasks.




RTOS Demo 7:

In this demo code, we mainly learn about 'rtos_await()'.

Two tasks run at the same rate (1000 ms).
The second task executes continuously and increments the global variable count each time it runs, while also displaying messages on the LCD.


The first task uses rtos_await(count == 10);, which means it will only execute its LCD display code when the condition count == 10 becomes true. If the condition is false, rtos_await() behaves like rtos_yield() and allows other tasks to run without blocking the system.



When count reaches 10 (after the second task has executed ten times), the first task performs its display actions and then resets count to 0, restarting the cycle.



This shows how can be used to implement conditional execution and simple event-driven synchronization between RTOS tasks without using semaphores.




RTOS Demo 8:

The codes show that RTOS is configured with a 100 ms minor cycle and statistics enabled. Two tasks are defined, both scheduled every 1000 ms. The second task intentionally increases its execution time on each loop iteration by incrementing a counter and introducing cumulative delays, eventually exceeding the allowed maximum execution time (max=100ms). When this happens, an overrun condition is detected and reported. Meanwhile, the first task periodically retrieves and prints statistical information about the second task's execution, including total runtime, minimum runtime, and maximum runtime.



The output shows that the second task is running, and the RTOS is measuring its execution time (task one). The total execution time continues to increase, while the shortest and longest times are recorded. When the task execution time exceeds the allowed limit (max=100 milliseconds), the message "The Second Task has Overrun" is displayed.

If I change the time of delay and cycle, the corresponding ticks will also be changed.






This allows us to observe how task execution time increases, how the RTOS records timing statistics, and how timeout events are detected and handled.

RTOS Demo 9:

In this Demo, we can use command to control the display on the LCD.

Two periodic tasks (Task1 and Task2) display messages on the LCD. A serial receive interrupt captures characters entered from the serial terminal and stores them in a buffer (input[30]). When the Enter key (0x0D) is pressed, the string is terminated with '\0', and the flag input_ready is set to TRUE to indicate that a complete command has been received.

A third task, The_kernal (running every 500 ms), continuously prompts with INPUT:> and waits (using rtos_yield()) until input_ready becomes TRUE. Depending on the command(which is shown below), it dynamically enables or disables Task1 or Task2 using rtos_enable() and rtos_disable().


If we enter 'disable2' 'enable1':



Then we enter'disable1' 'enable2':


If we disable both:


This shows how commands control the LCD in RTOS.


Comments

Popular posts from this blog

Blog 1 - Igor Kapusniak