0% found this document useful (0 votes)
121 views13 pages

FreeRTOS on ESP32: Lab 8 Guide

Lab 8 focuses on using FreeRTOS with the ESP32 microcontroller to perform concurrent tasks using the Arduino IDE. It covers the basics of FreeRTOS task states, API functions, and provides hands-on tasks for creating and managing tasks on the ESP32's dual cores. The lab also includes design tasks that require students to implement specific functionalities such as LED control and analog value reading.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
121 views13 pages

FreeRTOS on ESP32: Lab 8 Guide

Lab 8 focuses on using FreeRTOS with the ESP32 microcontroller to perform concurrent tasks using the Arduino IDE. It covers the basics of FreeRTOS task states, API functions, and provides hands-on tasks for creating and managing tasks on the ESP32's dual cores. The lab also includes design tasks that require students to implement specific functionalities such as LED control and analog value reading.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Lab 8: FreeRTOS on ESP32

FreeRTOS Basics
EE-423: Embedded System Design

Contents
1. Administrivia …………….....…………………………………………….2
1.1. Learning Objectives ……………………………….......…….…..2
1.2. Deliverables ………………………………….......……………...2
1.3. Hardware Resources ………………………………………….…2

2. FreeRTOS Task States ………………………...……………………….…3


2.1. FreeRTOS API Details…………………………………...……...3
2.2. ESP32 Dual Core Introduction…………………………………..4
2.3. Install ESP32 in Arduino IDE………………..……………...…..5

3. Arduino Sketch to find on which ESP32 Core Programming is Running...6


3.1. Steps to Upload the code to ESP32 Board………………………6
3.2. TASK A…………………………………………………………6
3.3. TASK B…………………………………………………………7

4. Concurrent Tasks running on a single core of ESP32…………………….8


4.1. TASK C………………………………………………………….8
4.2. TASK D………………………………………………………...10

5. Design Task……………………………………………………………...12
6. Design Task……………………………………………………………...12
1
1. Administrivia

1.1. Learning Objectives


By the end of this lab you will be able to:
1. To use FreeRTOS real-time operating system with Arduino IDE on ESP32 to
perform multiple specific tasks within a specified deadline.
2. To execute multiple threads or tasks on separate cores via FreeRTOS API
functions.

1.2. Deliverables
You are required to submit
• Code
• Observation and experiences
In the beginning of next lab.

1.3. Hardware Resources


• ESP32
• USB Mini Cable
• Potentiometer

2
2. FreeRTOS Task States
In the FreeRTOS a task can be in one of four different states, i.e., Running, Ready,
Blocked and Suspended as shown in below image.
• Running State: The task which is executing currently is said to be in running state.
It owns the CPU.
• Ready State: The task which is neither suspended nor blocked but still not
executing will be in ready state. It's not in running state because either a high
priority or equal priority task is executing.
• Blocked State: A task will go in blocked state whenever it is waiting for an event
to happen. The event can be completing a delay period or availability of a
resource. The blocked tasks are not available for scheduling.
• Suspended State: When vTaskSuspend() is called, the task goes in suspended
state. It can be resumed by calling xTaskResume(). The suspended tasks are also
not available for scheduling.

2.1. FreeRTOS API Details


• xTaskCreatePinnedToCore ( ): This interface is used to create a new Task.

• vTaskDelay ( ): This function is used to delay/block the task for specified delay
time(ticks).

• vTaskDelete ( ): This function is used to delete as task. We need to pass the


taskHandle of the task to be deleted. To delete the own task, we should pass
NULL as the parameter.

• vTaskPrioritySet ( ): This function is used to change/Set the priority of a task.


For this we need to pass the handle of the task and new priority to
vTaskPrioritySet() function.

• vTaskPriorityGet ( ): This function is used to get the priority of a task. For this, we
need to pass the handle of the task and it will return the task.

• vTaskSuspend ( ): This function is used to Suspend a task, the suspended remains


in the same state until it is resumed. For this, we need to pass the handle of the
tasks that needs to be suspended. Passing NULL will suspend own task.

3
• vTaskResume ( ): This function is used to resume a suspended task. If the
Resumed task has higher priority than the running task, then it will preempt the
running task or else stays in ready state. For this, we need to pass the handle of
the task to be resumed.

Fig.1 FreeRTOS Task States

2.2. ESP32 Dual Core Introduction


ESP32 module consists of two powerful 32-bit microprocessors which make it a dual-core
chip. This means that we can have two processes executing in parallel on two different
cores. Although, parallel operation can also be achieved on a single thread using
FreeRTOS/ any other equivalent RTOS. However, there is a difference between two
processes running in parallel on a single core, and they running in parallel on different
cores. On a single core, often, one thread has to wait for the other to pause before it can
begin execution. On two cores, parallel execution is literally parallel, because they are
literally occupying different processors.

4
When programming ESP32 using Arduino IDE, by default core1 is used and core0 is used
for RF communication. To run the program code on core0, some additional steps have to
be followed.

2.3. Install ESP32 in Arduino IDE


Open Arduino IDE and go to File -> Preferences.
Paste this link in Additional board manager URL
[Link]

Now you need to install library of ESP32 in Arduino IDE. To install library of ESP32 in
Arduino IDE, go to tools -> boards and click on board manager.
In search window write ESP32 and you will find of option of ESP32 by Espressif Systems.
Click on install button and install library of ESP32.

5
Now you have successfully installed the library of ESP32 development in Arduino IDE.

3. Arduino Sketch to find on which ESP32 Core Programming is Running


when we upload code to ESP32 Arduino IDE, the program runs on the ESP32 core1 by
default. In order to know which core is being used for respective tasks, you can use the
xPortGetCoreID() function. It will identify the core ID on which the core is running.

3.1. Steps to Upload the code to ESP32 Board


• Open your Arduino IDE and go to File -> New. A new file will open. Copy the code
given below in that file and save it.
• Go to Tools -> Board and select ESP32 Dev Module.
• Next, go to Tools -> Port and select the appropriate port through which your board
is connected.

3.2. Task A
Upload and try to understand the code. Write down your observation with output
screenshots.

6
void setup() {
[Link](115200);
[Link]("setup() is running on core ");
[Link](xPortGetCoreID());
}

void loop() {
[Link]("loop() is running on core ");
[Link](xPortGetCoreID());
}
Explanation:
• xPortGetCoreID(): This function returns the number of the kernel that is executing
the current task.
• Arduino sketches run on core 1 by default. You can verify the output on Serial
Monitor at a baud rate of 115200 that setup and loop function both are running
on core1 by default.
• To use core 0 you need to create tasks as explained in the next section.

3.3. Task B
Upload and try to understand the code. Write down your observation with output
screenshots.

Code:
1. TaskHandle_t Task1;
2. TaskHandle_t Task2;
3.
4. const int led = 2;
5. const int Analog_channel_pin= 15;
6. int ADC_VALUE = 0;
7.
8. void setup() {
9. [Link](115200);
10. pinMode(led, OUTPUT);
11.
12. xTaskCreatePinnedToCore(Task1code,"Task1",10000,NULL,1,&Task1,0);
13.
14. xTaskCreatePinnedToCore(Task2code,"Task2",10000,NULL,1,&Task2,1);
15. }
16.
17. void Task1code( void * parameter ){
18. [Link]("Task1 is running on core ");
19. [Link](xPortGetCoreID());
20.
21. for(;;){
22. digitalWrite(led, HIGH);
23. delay(500);
24. digitalWrite(led, LOW);

7
25. delay(500);
26. }
27. }
28.
29. void Task2code( void * parameter ){
30. [Link]("Task2 is running on core ");
31. [Link](xPortGetCoreID());
32.
33. for(;;){
34. ADC_VALUE = analogRead(Analog_channel_pin);
35. [Link]("ADC VALUE = ");
36. [Link](ADC_VALUE);
37. delay(1000);
38. }
39. }
40. void loop() { }

Explanation:

• xTaskCreatePinnedToCore: To pin a specific task to a specific core. This function


does exactly the same thing as xTaskCreate. However, we have an additional
parameter, which is where we will define in which core the task will be executed.
• Task 1 run on core 0 that blinks an LED attached to pin 2.
• Task 2 run on core 1 that read analog value by varying potentiometer knob
attached to pin 15.

4. Concurrent Tasks running on a single-core of ESP32


Upload and try to understand the code. Write down your observation with output
screenshots.

4.1. TASK C
Upload and try to understand the code. Write down your observation with output
screenshots.
Observe the output by commenting out vTaskDelay(), e.g. from Task 1 with output
screen shot.

Code:
void setup() {

[Link](112500);
delay(1000);

xTaskCreatePinnedToCore(
taskOne, /* Task function. */

8
"TaskOne", /* String with name of task. */
10000, /* Stack size in bytes. */
NULL, /* Parameter passed as input of the
task */
1, /* Priority of the task. */
NULL, /* Task handle. */
0); /* Task pinned to core n . */

xTaskCreatePinnedToCore(
taskTwo, /* Task function. */
"TaskTwo", /* String with name of task. */
10000, /* Stack size in bytes. */
NULL, /* Parameter passed as input of the
task */
2, /* Priority of the task. */
NULL, /* Task handle. */
0); /* Task pinned to core n . */

xTaskCreatePinnedToCore(
taskThree, /* Task function. */
"TaskThree", /* String with name of task. */
10000, /* Stack size in bytes. */
NULL, /* Parameter passed as input of the
task */
3, /* Priority of the task. */
NULL, /* Task handle. */
0); /* Task pinned to core n . */
}

void loop() {
}

void taskOne( void * pvParameters )


{

volatile int dummy = 0;


for(;;){
for(int i = 0;i<2000000;i++ ){
for(int j = 0;j<10;j++ ){
dummy += 1;
}
}

[Link](dummy);
[Link]("Running task 1");

//vTaskDelay(5000);
vTaskDelay(pdMS_TO_TICKS(5000)); /* Delay/Block the Task for exactly
5000 ms */
}
}

void taskTwo( void * pvParameters)


{
volatile int dummy2 = 0;
for(;;){
for(int i = 0;i<2000000;i++ ){

9
for(int j = 0;j<10;j++ ){
dummy2 += 1;
}
}

[Link](dummy2);
[Link]("Running task 2");

vTaskDelay(pdMS_TO_TICKS(5000)); /* Delay/Block the Task for exactly


5000 ms */
}
}

void taskThree( void * pvParameters)


{
volatile int dummy3 = 0;
for(;;){
for(int i = 0;i<2000000;i++ ){
for(int j = 0;j<10;j++ ){
dummy3 += 1;
}
}

[Link](dummy3);
[Link]("Running task 3");

vTaskDelay(pdMS_TO_TICKS(5000)); /* Delay/Block the Task for exactly


5000 ms */

}
}

// interesting execution behaviours are observed by commenting out


vTaskDelay(), e.g. from Task 1

4.2. TASK D
Upload and try to understand the code as well. Familiarize yourself with vTaskResume( )
and vTaskSuspend( ) APIs. Write down your observation with output screenshots.
Familiarize yourself with disableCore0WDT() and observe the effect of commenting out
line 4 with output screenshot.

Code:

//define task handles


TaskHandle_t TaskBlink_Handler;
TaskHandle_t TaskSerial_Handler;

# define LED_BUILTIN 2

10
void TaskBlink( void *pvParameters );
void TaskSerial(void* pvParameters);

void setup() {
// initialize serial communication at 115200 bits per second:
[Link](115200);
disableCore0WDT(); //disable TWDT for Core0

while (!Serial)
{ }

// Now set up two tasks to run independently.


xTaskCreatePinnedToCore(
TaskBlink
, "Blink" // A name just for humans
, 1000 // stack size
, NULL //Parameters passed to the task function
, 2 // Priority
, &TaskBlink_Handler,//Task handle
0); //Core

xTaskCreatePinnedToCore(
TaskSerial
, "Serial"
, 1000 // Stack size
, NULL //Parameters passed to the task function
, 1 // Priority
, &TaskSerial_Handler, //Task handle
0); //Core
}

void loop()
{
// Empty. Things are done in Tasks.
}

/*---------------------- Tasks ---------------------*/

void TaskSerial(void* pvParameters){

(void) pvParameters;
for (;;) // A Task shall never return or exit.
{
while([Link]()>0){
switch([Link]()){
case 's':
vTaskSuspend(TaskBlink_Handler);
[Link]("Suspend!");
break;
case 'r':
vTaskResume(TaskBlink_Handler);
[Link]("Resume!");
break;
}
vTaskDelay( 1 );
}

11
}

void TaskBlink(void *pvParameters) // This is a task.


{
(void) pvParameters;
pinMode(LED_BUILTIN, OUTPUT);
for (;;) // A Task shall never return or exit.
{
//[Link](11);
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on
vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second
digitalWrite(LED_BUILTIN, LOW); // turn the LED off
vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second
}
}

5. TASK E: Design Task


Write a code to create 2 tasks running on core 0 with same priority as mentioned below
• Task1: Blink an LED with 500ms frequency.
• Task 2: Read varying analog value generated using potentiometer which is
connected to pin 15. Display the value on Serial monitor which we got from the
ESP32 ADC with 300ms frequency.
Now change the task priorities such that Task 2 priority is higher than Task 1 and repeat
the same procedure.
Write down your observation with proper commented code and output screenshots.

6. TASK F: Design Task


Write a code to Control four LEDs with four different tasks. Set Digital pins 16 to 19 as
output pins and create 4 tasks with priorities (1-4) as mentioned below
• Task1: Set pin16 LED high with priority 2, while setting low on other LEDs with
100ms delay.
• Task2: Set pin17 LED high with priority 3, while setting low on other LEDs with
110ms delay.
• Task3: Set pin18 LED high with priority 4, while setting low on other LEDs with
120ms delay.

12
• Task4 (Idle Task): Set pin19 LED high with priority 1, while setting low on other
LEDs with 50ms delay.
Now change the task priorities in reverse order by keeping priority 1 for Task4 and
repeat the same procedure.
Write down your observation with proper commented code and output screenshots.

13

You might also like