Pertemuan OS - Id.en

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 11

Translated from Indonesian to English - www.onlinedoctranslator.

com

 OS MEETING SUMMARY

Test code from githubhttps://github.com/feilipu/Arduino_FreeRTOS_Library/tree/master


freeRTOS on arduino IDE.

1) Introduction FREERTOS Multitasking In Small Embedded Systems

FreeRTOS is a collection of C libraries consisting of a real-time kernel and a set of


Modular libraries that implement complementary functionality.

Richard Barry originally developed FreeRTOS around 2003. Real-Time Engineers Ltd,
Richard's company, continued FreeRTOS development in close partnership with the
world's leading chip companies until Amazon Web Services (AWS) took stewardship
of FreeRTOS 2016.

WHY USE AN RTOS?

There are many well-established techniques for writing good embedded software
without using a multithreading kernel. If the system under development is simple,
then these techniques might provide the most appropriate solution. Using a kernel
would likely be preferable in more complex cases, but where the crossover point
occurs will always be subjective.

As already described, task prioritization can help ensure an application meets its
processing deadlines, but a kernel can bring other less obvious benefits. Some of
these are listed very briefly below.

1. Abstracting away timing information

The RTOS is responsible for execution timing and provides a time-related API to the
application. That allows the structure of the application code to be more
straightforward and the overall code size to be smaller.

2. Maintainability/Extensibility

Abstracting away timing details results in fewer interdependencies between modules


and allows the software to evolve in a controlled and predictable way. Also, the
kernel is responsible for the timing, so application performance is less susceptible to
changes in the underlying hardware.

3. Modularity
Tasks are independent modules, each of which should have a well-defined purpose.

4. Team development

Tasks should also have well-defined interfaces, allowing easier team development.

5. Easier testing

Tasks that are well-defined independent modules with clean interfaces are easier to
test in isolation.

6. Code reuse

Code designed with greater modularity and fewer interdependencies is easier to


reuse.

7. Improved efficiency

Application code that uses an RTOS can be completely event-driven. No processing


time needs to be wasted by polling for events that have not occurred.

Countering the efficiency gained from being event driven is the need to process the
RTOS tick interrupt and switch execution from one task to another. However,
applications that don't use an RTOS normally include some form of tick interrupt
anyway.

8. Idle time

The automatically created Idle task executes when there are no application tasks that
require processing. The Idle task can measure spare processing capacity, perform
background checks, or place the processor into a low-power mode.

9. Power Management

The efficiency gains that result from using an RTOS allow the processor to spend
more time in a low power mode.

Power consumption can be decreased significantly by placing the processor into a


low power state each time the Idle task runs. FreeRTOS also has a special tick-less
mode. Using the tick-less mode allows the processor to enter a lower power mode
than would otherwise be possible and remain in the low power mode for longer.

10. Flexible interrupt handling


Interrupt handlers can be kept very short by deferring processing to either a task
created by the application writer or the automatically created RTOS daemon task
(also known as the timer task).

11. Mixed processing requirements

Simple design patterns can achieve a mix of periodic, continuous, and event-driven
processing within an application. In addition, hard and soft real-time requirements
can be met by selecting appropriate tasks and interrupt priorities.

2) The FreeRTOS Kernel Distribution

To help users orient themselves with the FreeRTOS kernel files and directories, this
chapter:

1. Provides a top-level view of the FreeRTOS directory structure.

2. Describes the source files required by any particular FreeRTOS project.


3. Introduces the demo applications.
4. Provides information on how to create a new FreeRTOS project.

 FreeRTOS Kernel Features

The FreeRTOS kernel has the following standard features:

1. Pre-emptive or co-operative operation


2. Optional time-slicing
3. Very flexible task priority assignment
4. Flexible, fast and light-weight task notification mechanisms
5. Queues
6. Binary semaphores
7. Counting semaphores
8. Mutexes
9. Recursive mutexes
10. Timer software
11. Event groups
12. Stream buffers
13. Message buffers
14. Co-routines (deprecated)
15. Tick hook functions
16. Idle hook functions
17. Stack overflow checking
18. Trace macros
19. Task run-time statistics gathering
20. Optional commercial licensing and support
21. Full interrupt nesting model (for some architectures)
22. A tick-less capability for extreme low power applications (for some
architectures)
23. Memory Protection Unit supports for isolating tasks and increasing application
safety (for some architectures)
24. Software managed interrupt stack when appropriate (this can help save RAM)
25. The ability to create RTOS objects using either statically or dynamically
allocated memory

 FreeRTOS Source Files Common to All Ports

tasks.c and list.c implement the core FreeRTOS kernel functionality and are always
required. They are located directly in the FreeRTOS/Source directory, as shown in
Figure 2.2. The same directory also contains the following optional source files:

1. queue.c

queue.c provides both queue and semaphore services, as described later in


this book. queue.c is almost always required.

2. timers. c

timers.c provides software timer functionality, as described later in this book. It


only needs to be built if the application uses software timers.

3. event_groups.c

event_groups.c provides event group functionality, as described later in this


book. It only needs to be built if the application uses event groups.
4. stream_buffer.c

stream_buffer.c provides both stream buffer and message buffer functionality,


as described later in this book. It only needs to be built if the application uses
streams or message buffers.

5. croutine.c

croutine.c implements the FreeRTOS co-routine functionality. It only needs to


be built if the application uses co-routines. Co-routines are intended for use
on very small microcontrollers, are rarely used now. They are, therefore, no
longer maintained, and their use is not recommended for new designs. Co-
routines are not described in this book.

 Variable Names

Variables are prefixed with their type: 'c' for char, 's' for int16_t (short), 'l' for int32_t
(long), and 'x' for BaseType_t and any other non-standard types (structures, task
handles, queue handles, etc.).
If a variable is unsigned, it is also prefixed with a 'u'. If a variable is a pointer, it is also
prefixed with a 'p'. For example, a variable of type uint8_t will be prefixed with 'uc',
and a variable of type pointer to char (char *) will be prefixed with 'pc'.

 Function Names

Functions are prefixed with both the type they return and the file they are defined
within. For example:

1. vTaskPrioritySet() returns a void and is defined within tasks.c.


2. xQueueReceive() returns a variable of type BaseType_t and is defined within
queue.c.
3. pvTimerGetTimerID() returns a pointer to void and is defined within timers.c.

File scope (private) functions are prefixed with 'prv'.

3)Heap Memory Management

The RTOS kernel needs RAM each time a task, queue, mutex, software timer,
semaphore or event group is created. The RAM can be automatically dynamically
allocated from the RTOS heap within the RTOS API object creation functions, or it
can beprovided by the application writer.
If RTOS objects are created dynamically then the standard C library malloc() and
free() functions can sometimes be used for the purpose, but...

1. they are not always available on embedded systems,


2. they take up valuable code space,
3. they are not thread safe, and
4. they are not deterministic (the amount of time taken to execute the function will differ
from call to call)

...so more often than not an alternative memory allocation implementation is required.

One embedded / real time system can have very different RAM and timing
requirements to another - so a single RAM allocation algorithm will only ever be
appropriate for a subset of applications.

4) Task Management

 Scope

1. How FreeRTOS allocates processing time to each task in an application.


2. How FreeRTOS chooses which task should execute at any given time.
3. How the relative priority of each task affects system behavior.
4. The states that a task can exist in.

 Task Functions

Tasks are implemented as C functions. Tasks must implement the expected function
prototype shown in Listing 4.1. which takes a void pointer parameter and returns
void. Code:void vATaskFunction( void * pvParameters );

 The Idle Task

The tasks created in Example 4.4 spend most of their time in the Blocked state. While
in this state, they are not able to run, so they cannot be selected by the scheduler.

There must always be at least one task that can enter the Running state 3. To ensure
this is the case, the scheduler automatically creates an Idle task when
vTaskStartScheduler() is called. The idle task does very little more than sitting in a
loop, so, like the task in the first example, it is always able to run.
The idle task has the lowest possible priority (priority zero), to ensure it never
prevents a higher priority application task from entering theRunningstate. However,
there is nothing to prevent application designers from creating tasks at, and
therefore share, the idle task priority, if desired. The configIDLE_SHOULD_YIELD
compile time configuration constant in FreeRTOSConfig.h can be used to prevent the
Idle task from consuming processing time that would be more productively allocated
to application tasks that also have a priority of 0. Section 4.12, Scheduling
Algorithms, describes configIDLE_SHOULD_YIELD.
Running at the lowest priority ensures the Idle task is transitioned out of
theRunningstate as soon as a higher priority task enters the Ready state. This can be
seen at time tn in Figure 4.9, where the Idle task is immediately swapped out to allow
Task 2 to execute at the instant Task 2 leaves theBlockedstate. Task 2 is said to have
preempted the idle task. Preemption occurs automatically, and without the
knowledge of the task being preempted.

 The Idle Task Hook

It is possible to add application specific functionality directly into the idle task
through the use of an idle hook (or idle callback) function, which is a function that is
called automatically by the idle task once per iteration of the idle task loop.

Common uses for the Idle task hook include:

 Executing low priority, background, or continuous processing functionality


without the RAM overhead of creating application tasks for the purpose.

 Measuring the amount of spare processing capacity. (The idle task will run
only when all higher priority application tasks have no work to perform; so
measuring the amount of processing time allocated to the idle task provides a
clear indication of spare processing time.)

 Placing the processor into a low power mode, providing an easy and
automatic method of saving power whenever there is no application
processing to be performed (although the achievable power saving is less
than that achieved by tick-less idle mode).

 MUTEX (MUTUAL EXLUSION)


Links:https://github.com/feilipu/Arduino_FreeRTOS_Library/blob/master/examples/Mutex/

Mutex.ino

1. Adjust Task Parameters to produce conflict.

To introduce conflicts between tasks, we can modify the parameters passed to the
xTaskCreate() function, in particular the delayTime parameter. We can adjust the delay time of
one of the tasks to use a shorter delay time of 500ms
Code:
void setup() {

Serial.begin(9600);

mutex = xSemaphoreCreateMutex();
if (mutex != NULL) {
Serial.println("Mutex created");
}

xTaskCreate(TaskMutex, "Task1", 128, (void*)1000, 1, NULL); // Task1


with a delay of 1000 ticks
xTaskCreate(TaskMutex, "Task2", 128, (void*)500, 1, NULL); // Tasks
with a delay of 500 ticks

2. Remove take and give semaphore to produce conflict.


Here is a modified TaskMutex function without semaphore operations:
Code:

void TaskMutex(void *pvParameters)


{
TickType_t delayTime = *((TickType_t*)pvParameters); // Use task
parameters to specify the delay

for (;;)
{
Serial.print(pcTaskGetName(NULL)); // Get the task name
Serial.print(", Read value Count: ");
Serial.print(globalCount);

globalCount++;

Serial.print(", Updated value: ");


Serial.print(globalCount);
Serial.println();

vTaskDelay(delayTime / portTICK_PERIOD_MS);
}
}

With this task modification, both tasks will directly access and modify the globalCount
variable without any synchronization mechanism. But a conflict occurred, so I added code like the
one below

 Semaphore is a tool used to organize access to shared resources between different tasks in the
system, before tasks access the globalCount variable, they must request "permission"
(semaphore) by using xSemaphoreTake(mutex, 10). Then, when it has finished accessing
globalCount, the task gives back those "permissions" using xSemaphoreGive(mutex).
 when we remove these two operations from the TaskMutex function, it means we remove
the command to ask permission (take) before accessing globalCount and give permission
back (give) after finishing accessing it.
 By removing this operation, both tasks no longer have to request permission before
accessing globalCount. They can access it immediately without waiting or coordinating with
other tasks. This can be problematic, because both tasks could attempt to access
globalCount at the same time, which could result in incorrect or inconsistent values. This is
the intended conflict, when tasks compete to access the same resources without
coordination.
If a conflict occurs, add a delay such as:

/**Create tasks*/
xTaskCreate(TaskMutex, // Task function
"Task1", // Task names for humans
128,
2000, // Task parameters
1, // Task priority
NULL);
xTaskCreate(TaskMutex, "Task2", 128, 2000, 1, NULL);

3. Mutex/Semaphore
 Mutex is a tool used in parallel programming to ensure that only one process or task
can access a shared resource at any given time. This helps prevent situations where two or
more processes try to access the same resource simultaneously, which could result in
inconsistent or even broken results. By using mutexes, we can ensure proper coordination
and synchronization between these processes, thereby ensuring organized and correct
execution in a parallel environment.
Mutex is implemented using the functions and data structures provided by FreeRTOS.
FreeRTOS provides functions such as xSemaphoreCreateMutex(), xSemaphoreTake(), and
xSemaphoreGive() to create, retrieve, and provide mutexes, which allows users to use the
mutex concept in embedded system development.
- Mutex is a special type of semaphore that has only two values
locked (locked) or not locked (unlocked).
- The main purpose of a mutex is to ensure that only one thread or process can
access a shared resource at any given time.
- Mutex to protect critical zones in a program and Only one thread can hold a
mutex at a time. If a mutex is being used by a particular thread, other threads
must wait until the mutex is released

 Semaphore
A semaphore is a special variable used to control access to a shared resource by multiple
threads or processes.
- has values that can be changed according to application needs
- two types of semaphore binary semaphore (or mutex) which has two values (0
or 1) and counting semaphore which has a value greater than zero.

4. Resource Management

Resource management is a principle that involves the management and allocation of


existing resources in a system. It includes managing resources such as memory, CPU,
hardware, and software to ensure efficient use among various processes or tasks. Resource
management is important to prevent conflicts between processes attempting to access the
same resources simultaneously, thereby ensuring optimal performance and system stability.

5. FreeRTOS Arduino Fundamentals //

 MULTITHREADING

Multithreading is a concept that allows a program to run several threads simultaneously.


A thread is a small unit of a process that can execute independently. In essence
multithreading allows running tasks simultaneously.

Code blink analog read:https://wokwi.com/projects/395913969394051073


Taskblink: tasked with endingWhen the LED flashes, this task uses the digitalWrite()
command to change the LED state from on to off and vice versa with a certain time interval
using the vTaskDelay() function.

TaskAnalogRead: This task reads the analog value from pin A0 and displays the value
to the Serial Monitor using the Serial.println() function. This task also uses the vTaskDelay()
function to provide a delay between reading analog values.

 THREADS

Multithreading (also called the concept of threads) => execution of several tasks
simultaneously on the Arduino platform.
The two tasks that are executed, namely TaskBlink and TaskAnalogRead, run independently
of each other. TaskBlink controls the LED to flash, while TaskAnalogRead reads the analog
value from the pin and displays it on the Serial Monitor.

 THREADS AND CONCURENCY

Two important concepts related to program execution

 Threads are small units of a process that can execute independently. A program can
have one or more threads running simultaneously. Threads allow programs to perform
multiple tasks simultaneously or in parallel.
 Concurrency is the ability of a program to handle multiple orders or requests. Where
every incoming order or request can be stacked/encumbered by one process.

You might also like