Single Core - Final Report
Single Core - Final Report
Single Core - Final Report
On
CERTIFICATE
This is to certify that the Major Project entitled “Parameters Estimation and
Performance Analysis of a Single-core processor using FreeRTOS” is submitted
by
Project Guide
Professor
Jawaharlal Nehru Technological University Hyderabad,
College of Engineering Hyderabad.
Department of Electronics and Communication Engineering
CERTIFICATE
This is to certify that the Major Project entitled “Parameters Estimation and
Performance Analysis of a Single-core processor using FreeRTOS” is submitted
by
Professor
Head of Department
ACKNOWLEDGEMENT
Along with our individual efforts in this project, we are grateful to be receiving
continuous support from our mentor, Dr. M. Asha Rani and the university. We would
like to extend our sincere thanks to all of them.
We are highly indebted to our mentor, Dr. M. Asha Rani, Professor, Department of
Electronics and Communication Engineering, JNTUH-CEH, for the kind co-operation
and encouragement which has helped us in the completion of this project.
(i)
DECLARATION
We hereby declare that the major project entitled “Parameters Estimation and
Performance Analysis of a Single-core processor using FreeRTOS” is the work done
during the period from December 2019 to June 2020 and is submitted in the partial
fulfilment of the requirements for the award of degree of Bachelor of Technology in
Electronics and Communication Engineering from JNTUH College of Engineering
Hyderabad. The results embodied in this project have not been submitted to any other
university or Institution for the award of any degree or diploma.
(ii)
TABLE OF CONTENTS
7 Software Development 63
and Implementation
8 Results and Discussion 84
References 90
(iii)
LIST OF FIGURES
(vi
(v)
LIST OF TABLES
8
(vi)
1. INTRODUCTION
When we hear the word operating system, the primary thought that strikes our
mind is that of the operating systems used in laptops & computers. Generally, we
use operating systems like windows XP, Linux, Ubuntu, Windows 7,8.8.1, and 10.
In the smartphones, the operating systems are like KitKat, Jellybean,
Marshmallow, and Nougat. In a digital electronic device, there is some sort of
operating system which is developed by the microcontroller program. There are
different types of operating systems to develop for the microcontroller, but our area
of interest over here is a real-time operating system (RTOS).
Why an RTOS? The obvious choice of an RTOS comes from the wide benefits it
offers. The real difference between an RTOS and a general-purpose OS is that with
an RTOS the designers have taken care to ensure that the response times are
known. This is not as simple as it may sound. Modern general-purpose operating
system kernels are very large, with several million lines of code. It can be difficult
to trace through them to find all the possible sources of delay in response. An
RTOS tends to be much smaller than a general-purpose OS making guarantying the
response time more practical. It is intended to serve real-time applications that
process data as it comes in, typically without buffer delays. At the beginning of this
documentation, we shall briefly scrutinize the advantages and classifications of an
RTOS.
We propose to run the applications on a microcontroller device using an RTOS, to
schedule tasks across its cores. A wide variety of RTOS are available in the market
today. The choice for our project is FreeRTOS. We shall also have an introspection
into its features and what makes it reliable for the project.
In this project, we intend to run one or more applications on the chosen
microcontroller, ESP32- a series of low-cost, low-power system on a chip
microcontroller with integrated Wi-Fi and dual-mode Bluetooth. ESP32 is a go-to
chip for making several devices as they’re small, powerful, have a ton of onboard
features, and they’re relatively easy to program, offering lesser challenges
compared to its vast advantages. We shall also dive into its features and try and
understand the pros and cons of the device. The ESP32 comes with a light
operating system – FreeRTOS. The methods to program this chip don’t replace the
FreeRTOS firmware, but rather deploy applications for it to run.
1
A further peek into this project shows us its aim at running different
applications(two) on the single-core processor and thereby, analysing the results.
The real time statistics are assessed and the performance shall be analysed for
different (two) scenarios.
2.1 Motivation:
Necessity is the mother of invention and embedded systems are inventions that
were fueled by the idea of making pre-programs to perform a dedicated narrow
range of functions as part of large systems. Embedded systems are being based
more on instruction-oriented design but not on design-oriented instructions.
Embedded systems and real-time operating systems (RTOS) are fast achieving
ubiquity, blurring the lines between science fiction and hard reality. In general,
an RTOS has features like multitasking, process threads that can be prioritized,
and a sufficient number of interrupt levels. An embedded system is any device
controlled by instructions stored on a chip. These devices are usually
controlled by a microprocessor that executes the instructions stored. With
these systems being widely used in devising many tools, we concern ourselves
with running applications on it, that use the benefits of RTOS.
Among the various RTOS available in the market, one is FreeRTOS. With an
available kernel for it, software developers gain great advantages. Application
code can be developed to be portable and flexible. FreeRTOS is a class of
RTOS that is designed to be small enough to run on a microcontroller –
although its use is not limited to microcontroller applications. Utilizing its
benefits and analyzing the performance is a benchmark initiative.
3.1 Introduction:
Beginning with the basic functionality of an Operating System, it hides the difficult
computations performed by hardware, which the software does on the back end.
We are presented a computer screen that we can work on and all other details that
is the communication between software and hardware is hidden form us. So, an
operating system is a type of software which communicates between application
software and hardware. Moving forward, we shall now discuss what is a real-time
operating system and what makes it more reliable.
Table 3.1 shows the differences between a real-time operating system(RTOS) and
a general purpose operating system(GPOS).
An operating system has to provide 3 essential things:
1. Task Scheduling:
The scheduler determines which task to run and when a task will run.
2. Task Dispatching:
The dispatcher handles the necessary operations to get a task ready to go.
3. Inter-task Communication:
This is the mechanism that handles how data and information is
exchanged between tasks and processes on the same machine or from
other machines.
These 3 essential things are what makes up the smallest portion of an OS called the
Kernel. The kernel is considered to be the core of an operating system. Its main
task is to manage the hardware and the processes running on it.
A real time operating system is just a special purpose operating system. The 'real
time' part of the name does not mean that the system responds quickly, it just
means that there are rigid time requirements that must be met. If these time
requirements are not met, the results can become inaccurate or unreliable.
RTOS GPOS
RTOS has unfair scheduling i.e. GPOS has fair scheduling i.e. it can be
scheduling is based on priority. adjusted dynamically for optimized
throughput.
It works under worst case assumptions. It optimizes for the average case.
So, the need to use an RTOS is when there is a need to monitor and control
physical processes in a timely manner. The constraints one has to deal with when
using RTOS are tight scheduling, predictability, and robustness.
As part of the embedded system abstraction layers, an RTOS is placed above the
low-level device drives and below the user application. The RTOS does not
provide low-level drivers for microcontroller peripherals. Some RTOS may
contain middleware software such as networking, file systems, etc.
Fig 3.2. RTOS within the embedded system abstraction layers
3.3.1 Tasks:
A piece of code performing a specific function is usually called a task. A task can
be also referred to as a thread, process, activity, etc. in different operating systems.
An operating system is expected to execute many different tasks at once – reading
inputs, outputting data, reacting to events, etc. A single microprocessor, however,
can execute code from only one task at a time. Achieving the required multitasking
is possible using a mechanism known as time multiplexing. Each task that the
operating system should execute is given a time window in which it can utilize the
CPU, and then the execution of another task proceeds according to a predefined
scheduling algorithm. If the timing requirements of all the tasks are fulfilled, we
can say we have concurrent like executions of multiple tasks without the use of
separate microprocessors for each task.
Multitasking is the way of sharing the processor’s time, so that a number of tasks
can execute pseudo-parallelly by taking turns to use the CPU. At any given point in
time, only one process can be present in the running state.
Running State: The task’s code is currently being executed by the CPU.
Ready State: The task is ready to be put into the running state. In the ready
state, the task does not consume any CPU cycles.
Blocked State: The task is in this state when it waits for the occurrence
of some event. In this state, the task does not consume any CPU cycles.
Suspended State: Tasks in the suspended state are not active anymore.
Some RTOS implementations may contain additional task states or have a different
naming convention than the ones listed above, but they are all following the same
logic.
Creating a task
Deleting a task
Changing the priority of the task
Changing state of the task
Messaging provides a means of communication with other system and between the
tasks. The messaging services include the following.
Semaphores
Event flags
Mailboxes
Pipes
Message queues
Semaphores are used to synchronize access to shared resources, such as common
data areas. Event flags are used to synchronize the inter-task activities. Mailboxes,
pipes, and message queues are used to send messages among tasks.
The most important part of the operating system is the Kernel. Tasks are relived of
monitoring the hardware. It’s the responsibility of the kernel to manage and
allocate the resources. As tasks cannot acquire CPU attention all the time, the
kernel must also provide some more services. These include the following.
Memory management
I/O system management
System protection
Networking
Command interruption
Time services
Device management services
Selecting a real-time operating system (RTOS) involves these five key features as
must-haves.
3.4.1. Reliability
Any RTOS must be reliable. This means that it operates for a reasonably long time
without human interference. Reliability also means the configuration to enable the
system to choose the right or most profitable action for current operations. For
example, a system for the telecom or banking industries needs to consider the cost
of terminating or engaging certain actions, compared to a phone or calculator
whose cost is limited to an individual, game, app function, etc.
3.4.2. Predictability
A system must execute actions within a known time frame and produce known
results. Such results are determined by the procedures or operations taking place.
The determination is by targets set during production or procedural planning.
3.4.3. Performance
Real-time operating systems are designed to make work easier. Every system must
solve a problem or reduce the workload. As such, the developer should provide a
system that is easily assimilated with existing software and hardware as well as
aligned to the goals of the organization.
3.4.4. Manageability
This means a system whose veracity or bulkiness is manageable. The software and
hardware required to operate the RTOS must be of reasonable size. Technicians
should also be easy to find and orient. The idea is to reduce the cost of
implementation.
3.4.5. Scalability
The needs of any production or event environment change with time. This means
that a system may require an upgrade or downgrade. Such provisions must be
made during design and installation of any RTOS.
Scheduling is the process of deciding which task should be executed at any point in
time based on a predefined algorithm. The logic for the scheduling is implemented
in a functional unit called the scheduler. The scheduling process is not present only
in RTOS, it can be found in one form or another even in simple “bare-bone”
applications.
As an example, let’s have three tasks called Task 1, Task 2 and Task 3. Task 1 has
the lowest priority and Task 3 has the highest priority. Their arrival times and
execute times are listed in the table below.
Task Name Arrival Time Execute
(microseconds) Time(microseconds)
Task1 10 50
Task 2 40 50
Task 3 40 40
In the table 3.1, we can see that Task 1 is the first to start executing, as it is the first
one to arrive (at t = 10 μs). Task 2 arrives at t = 40μs and since it has a higher
priority, the scheduler interrupts the execution of Task 1 and puts Task 2 into
running state. Task 3 which has the highest priority arrives at t = 60 μs. At this
moment Task 2 is interrupted and Task 3 is put into running state. As it is the
highest priority task it runs until it completes at t = 100 μs. Then Task 2 resumes its
operation as the current highest priority task. Task 1 is the last to complete is
operation.
In non-pre-emptive scheduling, the scheduler has more restricted control over the
tasks. It can only start a task and then it has to wait for the task to finish or for the
task to voluntarily return the control. A running task cannot be stopped by the
scheduler.
The non-pre-emptive scheduling can simplify the synchronization of the tasks, but
that is at the cost of increased response times to events. This reduces its practical
use in complex real-time systems.
We will now introduce some of the most popular scheduling algorithms that are
used in CPU scheduling. Not all of them are suitable for use in real-time embedded
systems. Currently, the most used algorithms in practical RTOS are round-robin
scheduling, and pre-emptive priority scheduling. In an attempt to present the right
explanation, the description and implementation of a few examples in simple C-
language are given.
In the shortest job first scheduling algorithm, the scheduler must obtain
information about the execution time of each task and it then schedules the one
with the shortest execution time to run next.
A disadvantage of this algorithm is that it requires the total execution time of a task
to be known before it is run.
Priority scheduling is one of the most popular scheduling algorithms. Each task is
assigned a priority level. The basic principle is that the task with the highest
priority will be given the opportunity to use the CPU.
RTOS is thereby, a preferred choice for many embedded device manufacturers and
embedded programmers. There are many RTOS flavours available. FreeRTOS is
widely followed by practitioners. Further from here, a detailed study on FreeRTOS
and its features is done to analyse what makes it the right choice for the project.
Every process in a computer system requires some amount of time for its
execution. This time is both the CPU time and the I/O time. The CPU time is the
time taken by CPU to execute the process. While the I/O time is the time taken by
the process to perform some I/O operation. In general, we ignore the I/O time and
we consider only the CPU time for a process. So, burst time is the total time
taken by the process for its execution on the CPU.
3.7.2 Arrival Time:
Arrival time is the time when a process enters into the ready state and is ready for
its execution.
Consider the following example.
Process Arrival time (in ms) Burst time (in ms)
P1 0 8
P2 1 7
P3 2 10
Table 3.3 Example for Arrival time determination
Here in the above example, the arrival time of all the 3 processes are 0 ms, 1 ms,
and 2 ms respectively.
Exit time is the time when a process completes its execution and exit from the
system.
Response time is the time spent when the process is in the ready state and gets the
CPU for the first time. For example, here we are using the First Come First Serve
CPU scheduling algorithm for the below 3 processes:
P1: 0 ms
P2: 7 ms because the process P2 have to wait for 8 ms during the execution
of P1 and then after it will get the CPU for the first time. Also, the arrival
time of P2 is 1 ms. So, the response time will be 8-1 = 7 ms.
P3: 13 ms because the process P3 have to wait for the execution of P1 and
P2 i.e. after 8+7 = 15 ms, the CPU will be allocated to the process P3 for
the first time. Also, the arrival of P3 is 2 ms. So, the response time for P3
will be 15-2 = 13 ms.
Response time = Time at which the process gets the CPU for the first time -
Arrival time
Waiting time is the total time spent by the process in the ready state waiting for
CPU. For example, consider the arrival time of all the below 3 processes to be 0
ms, 0 ms, and 2 ms and we are using the First Come First Serve scheduling
algorithm.
P1: 0 ms
P2: 8 ms because P2 have to wait for the complete execution of P1 and
arrival time of P2 is 0 ms.
P3: 13 ms because P3 will be executed after P1 and P2 i.e. after 8+7 = 15
ms and the arrival time of P3 is 2 ms. So, the waiting time of P3 will be:
15-2 = 13 ms.
Waiting time = Turnaround time - Burst time
In the above example, the processes have to wait only once. But in many other
scheduling algorithms, the CPU may be allocated to the process for some time
and then the process will be moved to the waiting state and again after some time,
the process will get the CPU and so on.
There is a difference between waiting time and response time. Response time is
the time spent between the ready state and getting the CPU for the first time. But
the waiting time is the total time taken by the process in the ready state. Let's take
an example of a round-robin scheduling algorithm. The time quantum is 2 ms.
P1 P2 P1 P2 P2
0ms 2ms 2ms 4ms 4ms 6ms 6ms 8ms 8ms 10ms
Table 3.8 Gnatt Chart
In the above example, the response time of the process P2 is 2 ms because after 2
ms, the CPU is allocated to P2 and the waiting time of the process P2 is 4 ms i.e
turnaround time - burst time (10 - 6 = 4 ms).
Turnaround time is the total amount of time spent by the process from coming in
the ready state for the first time to its completion.
or
For example, if we take the First Come First Serve scheduling algorithm, and the
order of arrival of processes is P1, P2, P3 and each process is taking 2, 5, 10
seconds. Then the turnaround time of P1 is 2 seconds because when it comes at
0th second, then the CPU is allocated to it and so the waiting time of P1 is 0 sec
and the turnaround time will be the Burst time only i.e. 2 seconds. The
turnaround time of P2 is 7 seconds because the process P2 have to wait for 2
seconds for the execution of P1 and hence the waiting time of P2 will be 2
seconds. After 2 seconds, the CPU will be given to P2 and P2 will execute its
task. So, the turnaround time will be 2+5 = 7 seconds. Similarly, the turnaround
time for P3 will be 17 seconds because the waiting time of P3 is 2+5 = 7 seconds
and the burst time of P3 is 10 seconds. So, turnaround time of P3 is 7+10 = 17
seconds.
Different CPU scheduling algorithms produce different turnaround time for the
same set of processes. This is because the waiting time of processes differ when
we change the CPU scheduling algorithm.
3.7.7 Throughput:
allocate only;
allocate and free with a very simple, fast, algorithm;
a more complex but fast allocate and free algorithm with memory coalescence;
an alternative to the more complex scheme that includes memory coalescence
that allows a heap to be broken across multiple memory areas.
and C library allocate and free with some mutual exclusion protection.
Here are some reasons why FreeRTOS is a good choice for our application:
Consider a Simple Digital Watch. Its only functionality is that it tells time. Such a
product can be developed using a simple 8-bit microcontroller and an operating
system is of very little use here as it only runs a single thread continuously. A
thread is basically a step by step process.
Now let’s add a little bit more complexity, Let’s add a stopwatch to the timer, and
an alarm clock and a count-down timer. Now the system has to run multiple tasks
at the same time. These tasks include
Now let’s add more functionality to our digital watch, let’s put in a pedometer, an
altimeter and a temperature sensor. Now the tasks that it needs to compute
parallelly includes
Now the system is not simple enough to be made using simple embedded operating
systems like FreeRTOS. It is still possible to do it but then the added complexity is
not easy for the development and maintenance of the system. Now we will
probably need a much more sophisticated Operating system like Embedded
Linux to accomplish our tasks.
This example gives us a brief idea of the places where simple embedded operating
systems like FreeRTOS fit in.
Tasks
Multitasking
Context switching
Schedulers
Kernels
Inter-task communications
Interrupts
We have previously looked into a few concepts like Tasks, Schedulers in the
previous chapter, Real-Time Operating System.
4.2.1 Tasks:
Any created task should never end before it is destroyed. It is common for task’s
code to be wrapped in an infinite loop, or to invoke vTaskDestroy(NULL) before it
reaches its final brace. As any code in infinite loop can fail and exit, it is safer even
for a repetitive task, to invoke vTaskDelete() before its final brace.
The task created using vTaskCreate() takes the following arguments.
pvTaskCode: A pointer to the function where the task is implemented.
pcName: It is the name given to the task. This is useless to FreeRTOS but is
intended for debugging purpose only.
usStackDepth: It is the length of the stack for this task in words. The actual
size of the stack depends on the microcontroller.
pvParameters: A pointer to arguments given to the task. A good practice
consists in creating a dedicated structure, instantiate and fill it then give its
pointer to the task.
uxPriority: Priority given to the task.
pxCreatedTask: A pointer to an identifier that allows to handle the task. If the
task does not have to be handled in the future, this can be leaved NULL.
When a task is deleted, it is responsibility of idle task to free all allocated memory
to this task by kernel. Notice that all memory dynamically allocated must be
manually freed.
Multitasking is the way of sharing the processor’s time, so that a number of tasks
can execute pseudo-parallelly by taking turns to use the CPU. At any given point in
time, only one process can be present in the running state. Other processes are
usually in one of the following 3 states. Ready state, Blocked state or Suspended
state. They have been discussed in detail in the previous chapter, Real-Time
Operating System.
The use of a multitasking operating system can simplify the design of what would
otherwise be a complex software application:
Multitasking Vs Concurrency
A conventional processor can only execute a single task at a time – but by rapidly
switching between tasks a multitasking operating system can make it appear as if
each task is executing concurrently. This is depicted by the diagram below which
shows the execution pattern of three tasks with respect to time. The task names are
colour coded and written down the left hand. Time moves from left to right, with
the coloured lines showing which task is executing at any particular time. The
upper diagram demonstrates the perceived concurrent execution pattern, and the
lower the actual multitasking execution pattern.
To prevent this type of error it is essential that upon resumption a task has a
context identical to that immediately prior to its suspension. The operating system
kernel is responsible for ensuring this is the case – and does so by saving the
context of a task as it is suspended. When the task is resumed its saved context is
restored by the operating system kernel prior to its execution. The process of
saving the context of a task being suspended and restoring the context of a task
being resumed is called context switching.
4.2.4 Schedulers:
Tasks are made to change from running state to one of the inactive states by
the scheduler by the process of pre-empting.
A currently running task is stopped without any notice, in favour of a higher
priority task, and its contents and status information are stored in memory so that
when it runs again, it can start from where it left off.
It is a task from the FreeRTOS operating system, whose task is to manage the state
of the other tasks.
It is the most important part of any real-time operating system. Its duty is to make
sure no lower priority tasks can be in running state while a higher priority task is in
the ready state so that the timing requirements can be met.
But as we just saw, the scheduler is also a task, which means it can only take a
limited amount of processor’s time, else it will do more harm than good as the
actual application needs to run on top of the operating system.
So, the scheduler usually runs once every fixed duration of time, say for example
once every 10 milliseconds. The scheduler occupies the CPU, say for 0.5ms and
during this time, it will see the manage the tasks so that only the highest priority
task in the ready state gets the next slot in time.
In the Fig 4.3, the green task is the scheduler. It starts at 0ms and runs till 0.5ms
and chooses Task1 to run till 10ms. Then at 10ms the scheduler comes back again
and this time picks another task to run from the ready queue which is Task 2 and
now Task 2 runs till 20ms.
Fig 4.3 Scheduler Task
If both the tasks of the same priority are in the ready state, then the scheduler will
choose the one that hasn’t had a chance to run for the longest period of time and
give it the next 9.5ms period to use the processor. Once that’s done the scheduler
comes in again and gives the CPU to the other same priority task. Thus, both these
tasks can take turns running of using the processor.
4.2.5 Kernel:
The kernel is considered to be the core of an operating system. Its main task is to
manage the hardware and the processes running on it.
The scheduler we saw above is the most important part of a kernel. Other
important parts include inter-task communications and synchronizations.
There are several options available for tasks to communicate with each other
through the kernel of FreeRTOS like queues, mutex, semaphores and notifications.
Queues:
Queues are the primary form of inter-task communications. They can be used to
send messages between tasks, and between interrupts and tasks. In most cases they
are used as thread safe FIFO (First In First Out) buffers with new data being sent to
the back of the queue, although data can also be sent to the front.
Fig 4.5 Writing to and reading from a queue. In this example the queue was created
to hold 5 items, and the queue never becomes full.
The FreeRTOS queue usage model manages to combine simplicity with flexibility
– attributes that are normally mutually exclusive. Messages are sent through
queues by copy, meaning the data (which can be a pointer to larger buffers) is
itself copied into the queue rather than the queue always storing just a reference to
the data. This is the best approach because:
Using queues that pass data by copy does not prevent queues from being
used to pass data by reference. When the size of a message reaches a point
where it is not practical to copy the entire message into the queue byte for
byte, define the queue to hold pointers and copy just a pointer to the
message into the queue instead. This is exactly how
the FreeRTOS+UDP implementation passes large network buffers around
the FreeRTOS IP stack.
The kernel takes complete responsibility for allocating the memory used
as the queue storage area.
Variable sized messages can be sent by defining queues to hold structures
that contain a member that points to the queued message, and another
member that holds the size of the queued message.
A single queue can be used to receive different message types, and messages
from multiple locations, by defining the queue to hold a structure that has a
member that holds the message type, and another member that holds the
message data (or a pointer to the message data). How the data is interpreted
depends on the message type. This is exactly how the task that manages
the FreeRTOS+UDP IP stack is able to use a single queue to receive
notifications of ARP timer events, packets being received from the Ethernet
hardware, packets being received from the application, network down
events, etc.
The implementation is naturally suited for use in a memory protected
environment. A task that is restricted to a protected memory area can pass
data to a task that is restricted to a different protected memory area
because invoking the RTOS by calling the queue send function will raise
the microcontroller privilege level. The queue storage area is only accessed
by the RTOS (with full privileges).
A separate API is provided for use inside of an interrupt. Separating the API
used from an RTOS task from that used from an interrupt service routine
means the implementation of the RTOS API functions do not carry the
overhead of checking their call context each time they execute. Using a
separate interrupt API also means, in most cases, creating RTOS aware
interrupt service routines is simpler for end users than when compared to
alternative RTOS products.
In every way, the API is simpler.
When a task attempts to read from an empty queue the task will be placed into the
Blocked state (so it is not consuming any CPU time and other tasks can run) until
either data becomes available on the queue, or the block time expires.
When a task attempts to write to a full queue the task will be placed into the
Blocked state (so it is not consuming any CPU time and other tasks can run) until
either space becomes available in the queue, or the block time expires.
If more than one task block on the same queue then the task with the highest
priority will be the task that is unblocked first.
See the Queue Management section of the user documentation for a list of queue
related API functions. Searching the files in
the FreeRTOS/Demo/Common/Minimal directory will reveal multiple examples of
their usage.
Note that interrupts must NOT use API functions that do not end in “FromISR”.
xQueueCreate returns NULL if the queue was not created due to lack of
memory available; if not, the returned value should be kept to handle the
newly created queue.
Mutex:
Mutex is used for controlling access to the shared resource. It is used to avoid
extended priority inversion using priority inheritance technique.
Priority inheritance can be implemented in two ways: changing the priority of the
task trying to access the mutex
1. to the priority equal to the priority of the task acquiring the mutex or
2. to the higher priority than the priority of the task acquiring the mutex
so that the task trying to access the mutex will immediately get the mutex
Semaphore:
Semaphores are just an extended version of mutexes. The shared resource guarded
by a mutex has only one key. On the other hand, the resource guarded by
semaphores can have multiple keys, so that a number of processes can access that
particular resource simultaneously.
Fug 4.6. Use case of a matrix
As an example, we can consider an elevator, which can support only four people at
a time. Here the elevator is the shared resource. If you need access to it, you need
to press the button outside the elevator signalling the elevator system that you need
to use it. Now if there is space in the elevator once it opens, say only one person is
already inside, then you can go in. But if there are already 4 people inside the
elevator, then you can either wait and take the next one.
Semaphores work much the same way. The elevator control system is analogous to
the kernel and the number of spaces available at any given time is analogous to the
number of free keys available to our shared resource at a given instant. If a key is
needed, it is asked for, from the kernel and if one is available, it will be given.
Since mutex and semaphores are so similar to each other, mutexes are also called
binary semaphores. Collectively mutexes, semaphores, queues, etc., are called
communication objects as they are used to communicate events, statuses and data
from one task to another task.
Creation of Semiphore:
Giving a Semiphore:
portBASE_TYPE xSemaphoreGive( xSemaphoreHandle xSemaphore );
The semaphore is not available, so the task is blocked, wating for the semaphore.
xSemaphoreTake()
xGiveSemaphoreFromISR() xSemaphoreTake()
xGiveSemaphoreFromISR() xSemaphoreTake()
xSemaphoreTake()
Another interrupt occurs and gives another semaphore. In the meanwhile, the task is processing
the first interrupt.
xGiveSemaphoreFromISR() xSemaphoreTake()
When the task has finished to preccess its first work, it waits for another semaphore and gets it
directly, since an interrupt occurred. The task is now able to process the second interrupt.
xSemaphoreTake()
4.2.7 Interrupts:
Interrupts behave in a way similar to the task switching mechanism available in the
scheduler so that the currently running code is pre-empted if an interrupt occurs,
task switching is done by the scheduler through software to make sure that a
lower priority task cannot run while another higher priority task is ready to run.
Interrupts are produced by hardware events like a user pressing a button.
Interrupts are used to capture events from the physical world the device is
working in while the task switching is done primarily for multitasking.
One of our tasks in this project is to determine the execution time and CPU
Utilization for the applications.
The execution time or CPU time of a given task is defined as the time spent by the
system executing that task, including the time spent executing run-time or system
services on its behalf. The execution time is implementation defined. It is
implementation defined which task, if any, is charged the execution time is
consumed by interrupt handlers and run-time services on behalf of the system.
CPU utilization is the sum of work handled by a Central Processing Unit. It is also
used to estimate system performance. CPU utilization can vary according to the
type and amount of computing task because some tasks require heavy CPU time
while others require less CPU time. Process time is another name for CPU time
and is the amount of time used by a CPU for processing instruction of an operating
system or a computer program. CPU time is quantified in clock ticks or
seconds. CPU utilization shows the burden on a processor in terms of percentage
that indicates if any changes are to be made in the system otherwise it may get
exhausted of capacity.
5. ESP32 – A FEATURE RICH MCU BOARD PORTED WITH FREERTOS
There are totally 39 digital Pins on the ESP32 out of which 34 can be used as
GPIO and the remaining are input only pins. The device supports 18-channels for
12-bit ADC and 2-channel for 8-bit DAC. IT also has 16 channels for PWM signal
generation and 10 GPIO pins supports capacitive touch features. The ESP32 has
multiplexing feature, this enables the programmer to configure any GPIO pin for
PWM or other serial communication though program. The ESP32 supports 3 SPI
Interface, 3 UART interface, 2 I2C interface, 2 I2S interface and also supports
CAN protocol.
Pin Pin Name Details
Category
Analog Pins ADC1_0 to ADC1_5 Used to measure analog voltage in the range of
and ADC2_0 to 0-3.3V.
ADC2_9
12-bit 18 Channel ADC
DAC pins DAC1 and DAC2 Used for Digital to analog Conversion
There are several use cases for wanting to multitask on a microcontroller. For
instance: you might have a microcontroller that reads a temperature sensor, shows
it on an LCD, and send it to the cloud. One can do all three synchronously, one
after the other. But what if one is using an e-ink display that takes a few seconds to
refresh? Luckily the implementation for the ESP32 includes the possibility to
schedule tasks with FreeRTOS. These can run on a single core; many cores and
one can even define which is more important and should get preferential treatment.
5.7 Programming:
Before programming this chip, it’s crucial to understand that, unlike other
embedded systems, the ESP32 comes with a light operating system - FreeRTOS.
The following methods to program this chip don’t replace the FreeRTOS firmware,
but rather deploy applications for it to run.
There are currently two methods to program the ESP32: the ESP-IDF and the
ESP32 Arduino Core. Using the Arduino IDE is easier. On the other hand, using
ESP-IDF gives more power. If we need more control over the hardware, like power
management, wireless power configuration or CPU core management, we’ll need
the ESP-IDF. Hence, we shall opt for ESP-IDF. Expressif included FreeRTOS in
its latest version ESP – IDF. In the subsequent chapters, we shall look into the
setting up of ESP-IDF environment., to be used in the project.
The vanilla FreeRTOS is designed to run on a single core. However, the ESP32 is
dual core containing a Protocol CPU (known as CPU 0 or PRO_CPU) and an
Application CPU (known as CPU 1 or APP_CPU). The two cores are identical in
practice and share the same memory. This allows the two cores to run tasks
interchangeably between them.
Given the specifications and features of the ESP32 board, one can see that it is
efficient, lighter and commercially reliable. The advantage that it comes with
FreeRTOS plays a crucial role, and thus, floats out to be the right choice for the
project.
6. SETTING UP ESP-IDF
The native software development framework for the ESP-32 is called the Espressif
IoT Development Framework (ESP-IDF). It provides maximum functionality and
compatibility. It is a bit hard core than some of the other programming options but
it gives a better understanding of what is happening under the hood.
Hardware:
An ESP32 board.
USB cable – USB A / micro USB B.
Computer running Windows, Linux, or mac
OS. Software:
The installer includes the cross-compilers, OpenOCD, CMake and Ninja build tool.
The installer can also download and run installers for Python 3.7 and Git For
Windows if they are not already installed on the computer.
The installer also offers to download one of the ESP-IDF release versions.
For the remaining Getting Started steps, we’re going to use the Windows
Command Prompt.
ESP-IDF Tools Installer creates a shortcut in the Start menu to launch the ESP-IDF
Command Prompt. This shortcut launches the Command Prompt (cmd.exe) and
runs export.bat script to set up the environment variables
( PATH , IDF_PATH and others). Inside this command prompt, all the installed
tools are available.
Note that this shortcut is specific to the ESP-IDF directory selected in the ESP-IDF
Tools Installer. If you have multiple ESP-IDF directories on the computer (for
example, to work with different versions of ESP-IDF), you have two options to use
them:
1. Create a copy of the shortcut created by the ESP-IDF Tools Installer, and
change the working directory of the new shortcut to the ESP-IDF directory you
wish to use.
2. Alternatively, run cmd.exe , then change to the ESP-IDF directory you wish to
use, and run export.bat . Note that unlike the previous option, this way requires
Python and Git to be present in PATH . If you get errors related to Python or
Git not being found, use the first option.
To build applications for the ESP32, we need the software libraries provided by
Espressif in ESP-IDF repository.
To get ESP-IDF, navigate to the installation directory and clone the repository with
git clone . In addition to installing the tools, for Windows introduced in Step 1 can
also download a copy of ESP-IDF.
Aside from the ESP-IDF, you also need to install the tools used by ESP-IDF, such as
the compiler, debugger, Python packages, etc. for Windows introduced in Step 1
installs all the required tools.
In order to install the tools without the help of ESP-IDF Tools Installer, open the
Command Prompt and follow these steps:
cd %userprofile%\esp\esp-idf install.bat
The scripts introduced in this step install compilation tools required by ESP-IDF
%USERPROFILE%\.espressif
inside the user home directory:on Windows andon Linux . To install the tools
$HOME/.espressif
into a different directory, set
IDF_TOOLS_PATH
the environment variablebefore running the installation
scripts. Make sure that the user account has sufficient permissions to read and
write this path.
%userprofile%\esp\esp-idf\export.bat
On Linux, in the terminal where you are going to use ESP-IDF, run:
. $HOME/esp/esp-idf/export.sh
Step 5: Start a Project:
We are now ready to prepare the first application for ESP32.
cd %userprofile%\esp
xcopy /e /i %IDF_PATH%\examples\get-started\hello_world hello_world
On Linux,
cd ~/esp
cp -r $IDF_PATH/examples/get-started/hello_world .
On Linux,
cd ~/esp/hello_world
idf.py set-target esp32
idf.py menuconfig
idf.py build
This command will compile the application and all ESP-IDF components, then it
will generate the bootloader, partition table, and application binaries.
$ idf.py build
Running cmake in directory /path/to/hello_world/build
Executing "cmake -G Ninja --warn-uninitialized /path/to/hello_world"...
Warn about uninitialized values.
-- Found Git: /usr/bin/git (found version "2.17.0")
-- Building empty aws_iot component due to configuration
-- Component names: ...
-- Component paths: ...
When flashing, we will see the output log similar to the following:
...
esptool.py --chip esp32 -p /dev/ttyUSB0 -b 460800 --before=default_reset --
after=hard_reset write_flash --flash_mode dio --flash_freq 40m --flash_size 2MB
0x8000 partition_table/partition-table.bin 0x1000 bootloader/bootloader.bin
0x10000 hello-world.bin
esptool.py v3.0-dev
Serial port /dev/ttyUSB0
Connecting......._
Chip is ESP32D0WDQ6 (revision 0)
Features: WiFi, BT, Dual Core, Coding Scheme None
Crystal is 40MHz
MAC: 24:0a:c4:05:b9:14
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 460800
Changed.
Configuring flash size...
Compressed 3072 bytes to 103...
Writing at 0x00008000. . .(100 %)
Wrote 3072 bytes (103 compressed) at 0x00008000 in 0.0 seconds (effective
5962.8 kbit/s)...
Hash of data verified.
Compressed 26096 bytes to 15408...
Writing at 0x00001000. . .(100 %)
Wrote 26096 bytes (15408 compressed) at 0x00001000 in 0.4 seconds (effective
546.7 kbit/s)...
Hash of data verified.
Compressed 147104 bytes to 77364...
Writing at 0x00010000. . .(20 %)
Writing at 0x00014000. . .(40 %)
Writing at 0x00018000. . .(60 %)
Writing at 0x0001c000. . .(80 %)
Writing at 0x00020000. . .(100 %)
Wrote 147104 bytes (77364 compressed) at 0x00010000 in 1.9 seconds (effective
615.5 kbit/s)...
Hash of data verified.
Leaving...
Hard resetting via RTS pin...
Done
If there are no issues by the end of the flash process, the board will reboot and start
up the “hello_world” application.
...
Hello world!
Restarting in 10 seconds...
This is esp32 chip with 2 CPU cores, WiFi/BT/BLE, silicon revision 1, 2MB
external flash
Restarting in 9
seconds... Restarting in
8 seconds... Restarting
in 7 seconds...
To exit IDF monitor use the shortcut Ctrl+] .
1.
2. +--esp-
idf 3.|
4. |
5. + - - components
6. |
7. + - - docs
8. |
9. + - - examples
10. |
11. + - - make
12. |
13. + - - tools
The components directory holds all the 'C' code for the ESP32. It contains all the
'components' that make up the ESP32. It includes Drivers for numerous
peripherals, the bootloader, bt(bluetooth), freeRTOS etc. If we expand the
components the tree looks like so:
1. +---components
2. | +---app_update
3. | | | component.mk
4. | | | esp_ota_ops.c
5. | | |
6. | | \---include
7. | | esp_ota_ops.h
8. | |
9. +---bootloader
| | | | component.mk
10.
11. | | | README.rst
12. | | |
13. | | +---include
14. | | | esp_image_format.h
15. | | | esp_secure_boot.h
16. | | |
17. | | +---include_priv
18. | | | bootloader_flash.h
19. | | |
20. | | \---src
21. | | bootloader_flash.c
22. | | esp_image_format.c
23. | | secure_boot.c
24. | | secure_boot_signatures.c
25. | |
26. | +---bt
27. | | | bt.c
28. . .
29. | |
30. | +---driver
31. | | | component.mk
32. | | | gpio.c
33. . .
34. | |
35. | +---esp32
36. | | | abi.cpp
37. . .
38. | |
39. | +---esptool_py
40. | | | Kconfig.projbuild
41. . .
42. | |
43. | +---ethernet
44. | | | component.mk
45. . .
46. | |
47. | +---expat
48. . .
49. | |
50. | +---freertos
51. | | | component.mk
52. . .
53. | |
54. | +---idf_test
55. . .
56. | |
57. | +---newlib
58. . .
59. | |
60. | +---nghttp
61. . .
62. | |
63. | +---nvs_flash
64. | | | .gitignore
65. | |
66. . .
67. | |
68. | +---openssl
69. | |
70. . .
71. | |
72. | +---partition_table
73. . .
74. | |
75. | +---spi_flash
76. | |
77. . .
78. | |
79. | +---tcpip_adapter
80. . .
81. | |
82. | +---ulp
83. | |
84. . .
85. | |
86. | +---vfs
87. | |
88. . .
89. | +---wpa_supplicant
90. | |
91. | \---xtensa-debug-module
92. | | component.mk
93. . .
94. |
95. |
96. +--- docs
1. #include <stdio.h>
2. #include "freertos/FreeRTOS.h"
3. #include "freertos/task.h"
4. #include "esp_system.h"
5. #include "driver/gpio.h"
6.
7. #define BLINK_GPIO 13
7.1 Development:
Before getting in to the program development, let us take a look at the folder where
the source code is to be stored and additional documents are required for the
program to function properly.
The folder is as shown below:
From the above picture, one can see that the program folder consists of a main
folder, cmakeLists.txt, makefile, README.md,sdkconfig.defaults.
1.CMakeLists.txt file contains a set of directives and instructions describing the
project's source files and targets (executable, library, or both).
2.A makefile is a special file, containing shell commands, that you create and
name makefile (or Makefile depending upon the system). While in the directory
containing this makefile, you will type make and the commands in the makefile
will be executed.
3.A README file contains information about other files in a directory or archive
of computer software. A form of documentation, it is usually a simple plain text
file called READ.ME, README.TXT, README.md.
After building the project, the project folder will be as shown below:
A new folder called as build has been created which stores all the details related to
building the project.
An additional sdkconfig.old document is created which contains the default
configuration details and the sdkconfig folder is updated to the recent developments.
7.2 Program:
Since we are now familiar with the structure of the program as seen in the Hello
World task earlier, let us proceed to the program development.
The source code of the project for the single core processor is given below:
#include <stdio.h>
#include <math.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#define pi 3.14159265
while(1) {
long c;
c=a*b;
printf("Multiplication of %d and %d is %ld\n",a,b,c);
a+=1;
b+=1;
vTaskDelay(200 / portTICK_RATE_MS);
}
}
void add(void *pvParameter)
{
int a=6,b=3;
while(1) {
long c;
c=a+b;
printf("sum of %d and %d is %ld\n",a,b,c);
a+=1;
b+=1;
vTaskDelay(200 / portTICK_RATE_MS);
}
}
void sub(void *pvParameter)
{
int a=6,b=3;
while(1) {
int c;
c=a-b;
printf("subtraction of %d and %d is %d\n",a,b,c);
a+=2;
b+=1;
vTaskDelay(200 / portTICK_RATE_MS);
}
}
double x,rescos,ressine,restan,val;
x=30;
while(1)
{ val=pi/180.0;
rescos=cos(x*val);
ressine=sin(x*val);
restan=tan(x*val);
printf("The cosine of %lf degrees is %lf\n",x,rescos);
printf("The sine of %lf degrees is %lf\n",x,ressine);
printf("The tangent of %lf degrees is %lf\n",x,restan);
x+=15;
vTaskDelay(200 / portTICK_RATE_MS);
}
}
void compadd(void *pvParameter){
int a1=2,b1=4,a2=3,b2=1;
int a3,b3;
while(1)
{
a3=a1+a2;
b3=b1+b2;
printf("The sum of %d+i%d and %d+i%d is %d+i%d\n",a1,b1,a2,b2,a3,b3);
a1+=1;
a2+=2;
b1+=-1;
vTaskDelay(200 / portTICK_RATE_MS);
}
}
void compsub(void *pvParameter){
int a1=2,b1=4,a2=3,b2=1;
int a3,b3;
while(1)
{
a3=a1-a2;
b3=b1-b2;
printf("The difference of %d+i%d and %d+i%d is %d+i%d\n",a1,b1,a2,b2,a3,b3);
a1+=3;
a2+=1;
b1+=2;
vTaskDelay(200 / portTICK_RATE_MS);
}
}
void compmul(void *pvParameter){
int a1=2,b1=4,a2=3,b2=1;
int a3,b3;
while(1)
{
a3=(a1*a2-b1*b2);
b3=(a1*b2+a2*b1);
printf("The multiplication of %d+i%d and %d+i%d is
%d+i%d\n",a1,b1,a2,b2,a3,b3);
a1+=3;
a2+=1;
b1+=2;
vTaskDelay(200 / portTICK_RATE_MS);
}
}
void temp(void *pvParameter){
float c=23;
while(1)
{
float f,k;
f=((c*1.8)+32.0);
k=c+273.15;
printf("The farenheit temperature for given %f celcius is %f farenheit\n",c,f);
printf("The kelvin temperature for given %f celcius is %f kelvin\n",c,k);
c=c+1.5;
vTaskDelay(200 / portTICK_RATE_MS);
}
}
void app_main()
{
xTaskCreatePinnedToCore(&division, "division", 2048, NULL, 10, NULL, 0);
xTaskCreatePinnedToCore(&mul, "mul", 2048,NULL,8,NULL ,0);
xTaskCreatePinnedToCore(&add, "add", 2048,NULL,6,NULL,0);
xTaskCreatePinnedToCore(&sub, "sub", 8192,NULL,5,NULL,0 );
xTaskCreatePinnedToCore(&square, "square", 4096,NULL,3,NULL,0 );
xTaskCreatePinnedToCore(&sqart, "sqart", 16384,NULL,15,NULL,0);
xTaskCreatePinnedToCore(&logarithimic, "logarithimic", 4096,NULL,2,NULL,0
);
xTaskCreatePinnedToCore(&trig, "trig", 8192,NULL,2,NULL,0 );
xTaskCreatePinnedToCore(&temp, "temp", 2048,NULL,2,NULL,0 );
xTaskCreatePinnedToCore(&compadd, "compadd", 2048,NULL,3,NULL,0 );
xTaskCreatePinnedToCore(&compsub, "compsub", 2048,NULL,4,NULL,0 );
xTaskCreatePinnedToCore(&compmul, "compmul", 2048,NULL,5,NULL,0 );
#include <stdio.h>
#include <math.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "driver/gpio.h"
main function:
The program execution starts with the app_main(), just like good old main(). This
is the first function that gets called automatically.
Example:
void app_main()
{
xTaskCreate():
Each task requires RAM that is used to hold the task state, and used by the task as
its stack. If a task is created using xTaskCreate() then the required RAM is
automatically allocated from the FreeRTOS heap.
Parameters:
pvTaskCode: Pointer to the task entry function i.e; the address of the
task.Tasks are normally implemented as an infinite loop, and must never
attempt to return or exit from their implementing function. Tasks can
however delete themselves.
pcName: A descriptive name for the task. This is mainly used to facilitate
debugging, but can also be used to obtain a task handle.The maximum
length of a task’s name is set using the configMAX_TASK_NAME_LEN
parameter in FreeRTOSConfig.h.
usStackDepth: The number of words (not bytes!) to allocate for use as the
task’s stack.
pvParameters: A value that will passed into the created task as the task’s
parameter.If pvParameters is set to the address of a variable then the variable
must still exist when the created task executes – so it is not valid to pass the
address of a stack variable.
Returns:
If the task was created successfully then pdPASS/pdTRUE is returned. Otherwise
errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY is returned.
xTaskCreatePinnedToCore():
This function is similar to xTaskCreate, but allows setting task affinity in SMP
system.
xTaskCreatePinnedToCore( TaskFunction_t pvTaskCode,
const char * const pcName,
configSTACK_DEPTH_TYPE usStackDepth,
void *pvParameters,
UBaseType_t uxPriority,
TaskHandle_t *pxCreatedTask
const BaseType_t xCoreID
);
Parameters:
pvTaskCode: Pointer to the task entry function i.e; the address of the
task.Tasks are normally implemented as an infinite loop, and must never
attempt to return or exit from their implementing function. Tasks can
however delete themselves.
pcName: A descriptive name for the task. This is mainly used to facilitate
debugging, but can also be used to obtain a task handle.The maximum
length of a task’s name is set using the configMAX_TASK_NAME_LEN
parameter in FreeRTOSConfig.h.
usStackDepth: The number of words (not bytes!) to allocate for use as the
task’s stack.
pvParameters: A value that will passed into the created task as the task’s
parameter.If pvParameters is set to the address of a variable then the variable
must still exist when the created task executes – so it is not valid to pass the
address of a stack variable.
The task:
Consider a task from the above program and the structure is as shown below:
void add(void *pvParameter)
{
int a=6,b=3;
while(1) {
long c;
c=a+b;
printf("sum of %d and %d is %ld\n",a,b,c);
a+=1;
b+=1;
vTaskDelay(200 / portTICK_RATE_MS);
}
}
Here, the functionality of the task is written in the while loop that run infinitely as
a task in the freertos should run infinitely and it should never attempt to return or
exit from the implementing function.
Now, inorder to facilitate the executio of other tasks, we introduce a delay in the
task through vTaskDelay.
vTaskDelay:
void vTaskDelay( const TickType_t xTicksToDelay );
vTaskDelay() specifies a time at which the task wishes to unblock relative to the
time at which vTaskDelay() is called. For example, specifying a block period of
100 ticks will cause the task to unblock 100 ticks after vTaskDelay() is called.
Parameters:
xTicksToDelay: The amount of time, in tick periods, that the calling task
should block.
Example usage:
for( ;; )
{
/* Simply toggle the LED every 500ms, blocking between each toggle. */
vToggleLED();
vTaskDelay(500 / portTICK_PERIOD_MS;);
}
}
Runtime Stats:
In order to get the information about the tasks running and the run time statistics of
the program, two APIs are used. Their functionality is described below:
vTaskList():
In the ASCII table the following letters are used to denote the state of a task:
‘B’ – Blocked
‘R’ – Ready
‘D’ – Deleted (waiting clean up)
‘S’ – Suspended, or Blocked without a timeout
Parameters:
pcWriteBuffer : A buffer into which the above mentioned details will be
written, in ASCII form. This buffer is assumed to be large enough to
contain the generated report. Approximately 40 bytes per task should be
sufficient.
Parameters:
pcWriteBuffer: A buffer into which the execution times will be written,
in ASCII form. This buffer is assumed to be large enough to contain the
generated report. Approximately 40 bytes per task should be sufficient.
7.3 Implementation:
The following are the steps to be followed for implementing the project in a
LINUX based system:
1) Adding tools to the environment
Before proceedingg to compiling and building the projet ensure that all the tools
must be added to the path so as to function. For this to be done, navigate to the
folder where the esp-idf software is stored and then type the command .
./export.sh. This will ensure that all the tools are added to the path for smooth
functioning of the build process.
Fig 7.5 Adding tools to the environment
Now, navigate to the serial flasher config(shown below), at the top is the name of
the serial port to which the component is to attached, now set the flash size to
2MHz
and the baud rate to 115200bps and the flash SPI speed to 40MHZ(These are to be
done according to the board that one uses).
In the present project, the performance of the FreeRTOS kernel using ESP32 board
was analysed through different parameters. The explanation about the importance
of using RTOS in critical time systems was also accomplished and proved.
Considering the circumstances of the experiments, it is possible to conclude that
the FreeRTOS kernel really presented determinism and reliability. Such kernel
may be considered useful and flexible with free open source libraries. The
FreeRTOS libraries are written in C programming language, being very easy to
become acquainted with.
The embedded system ESP32 demonstrated a good performance with simplicity,
low cost reliability, and feasibility. The board has a very small size, demonstrating
a good capability of being installed in any further projects, when portability is
necessary. As displayed in the project, this device may be considered useful for the
proposed application and other applications involving RTOS. ESP32 is a dual-core
processor and the project successfully runs the application on one of the two cores.
From the results, we can conclude that the performance varies with the number of
tasks involved in the application. The first application takes longer execution time
than the second as the number of tasks are more. When coming to the CPU
Utilization, though the number of tasks in both the applications differ by a
significant amount, there is only a slight change in the percentage of CPU
Utilization. The first application runs 18 tasks utilizing 29% whereas the second
applications runs 10 tasks utilizing 27%. This proves that CPU Utilization depends
not just on the number of tasks but also on the complexity and type of the
computing task.
Single core processor consumes less. With more cores, it is found that battery
drains quickly. The number of applications we can run on the core before the
battery drains are comparatively more. Because single-core processor consumes
less power, the entire system being run by it remains cooler. A single core
processor is still good for most of applications because many of them aren’t built
for multiple core processor. The disadvantage steps in as it is comparatively a slow
processor. It takes more time as the time taken by every task counts in and the CPU
utilization cannot be directly told by the tasks involves in the application.
From this project we conclude that, RTOS is very important to handle critical time
systems, which become useless after missing the deadline. Also, we have seen the
capabilities of the ESP32 board, and up to what extent a single-core processor is
reliable. For simpler applications which do not rely on the time required to obtain
the results, it is easy to use the single processor as it adds very few lines to the
original code. Moreover, it consumes lesser power. But on the other hand, when
projects are to have quick results, the reliability on the processor ends. If a single
core processor is assigned with two difference things, it cannot do them both
simultaneously. Because modern apps require a lot of processing power, a single-
core processor operating them can get frozen. It simply means that the entire
system can become unresponsive. Depending on the needs required to meet the
project, one can choose to whether or not go for the single-core. From this project,
it is also possible to conclude that there is a very rich field involving RTOS
applications for embedded tasks.
Future Scope:
Microprocessors have found their way in almost every electronic device that is
available today. Microprocessors and microcontrollers enable the modern world to
produce devices that comprehend the environment and react to situations
producing a much-desired effect. The operating speed of modern day computers
has increased over a thousand times in the past twenty years.
It’s not hard to predict that next-generation processors will have smaller details,
more transistors on each square millimeter of silicon, and do more clever things,
such as powering down under-used sections even between keystrokes. They will
also have many cores or CPUs.
Even now, Intel has given hardware and software developers a peek at a
prototype 80-core processor with one teraflop of computational ability. The
company, however, has set no launch date. Nvidia Corp. sells a Quadro Plex
graphic processor sporting 128 cores. And Cisco Systems Inc., sensing a coming
surge in network traffic, is toying with a 188-core router.
REFERENCES
(1) https://www.freertos.org/FreeRTOS-quick-start-guide.html
(2) https://www.freertos.org/a00019.html
(3) https://www.freertos.org/a00021.html#vTaskList
(4) https://www.freertos.org/a00021.html#vTaskGetRunTimeStats
(5) https://www.freertos.org/RTOS-message-buffer-API.html
(6) Using the FreeRTOS Real-time Kernel- A Practical Guide by Richard Barry
(7) ESP-IDF Programming Guide — ESP-IDF
Programming Guide documentation
(8) https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-
started/linux- setup.html
(9) https://docs.aws.amazon.com/freertos/latest/userguide/what-is-
freertos.html