Está en la página 1de 12

Sistemas Embebidos

Práctica de Laboratorio 1: Introducción a FreeRTOS

Presentado por:

Elián Andrés Díaz Vargas

Presentado a:

Ing. José Jorge Carreño Zagarra

Universidad Santo Tomás, Bucaramanga


17 octubre de 2021
1. Task_FreeRTOS:
• Código:
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "driver/gpio.h"

#define BLINK_GPIO 2 // se define la Gpio2

void hello_task(void *pvParameter) // funcion que imprime Hello world!


cada 100 ms
{
while(1) // ciclo infinito
{
printf("Hello world!\n"); // imprime en pantalla
vTaskDelay(100 / portTICK_RATE_MS); // delay de 100 ms
}
}
void blinky(void *pvParameter) // funcion encender led
{
gpio_pad_select_gpio(BLINK_GPIO); // se selecciona la GPIO a utilizar
/* Set the GPIO as a push/pull output */
gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT); // se dispone de la
GPIO2 como salida
while(1) { // ciclo infinito
/* Blink off (output low) */
gpio_set_level(BLINK_GPIO, 0); // Se envía un cero a la Gpio2
(led apagado)
vTaskDelay(1000 / portTICK_RATE_MS); // delay de 1 segundo
/* Blink on (output high) */
gpio_set_level(BLINK_GPIO, 1); // Se envía un uno a la Gpio2 (led
encendido)
vTaskDelay(1000 / portTICK_RATE_MS); // delay de 1 segundo
}
}
void app_main() // funcion principal
{
xTaskCreate(&hello_task, "hello_task", 2048, NULL, 5, NULL); // se
llama a la funcion que imprime hello world
// se le
coloca un nombre para identificar la tarea
// se
define el tamao de la memoria a utilizar
//Un
valor que se pasa como parámetro a la tarea creada.
//se
define la prioridad de la tarea
//Se
pasa un identificador a la tarea creada fuera de la funcion
xTaskCreate().
xTaskCreate(&blinky, "blinky", 512,NULL,5,NULL ); // se llama a la
funcion que imprime enciende y apaga un led
// se le coloca un
nombre para identificar la tarea
// se define el
tamao de la memoria a utilizar
//Un valor que se
pasa como parámetro a la tarea creada.
//se define la
prioridad de la tarea
//Se pasa un
identificador a la tarea creada fuera de la funcion xTaskCreate().
}

• Explicación código:
- Inicialmente se hace una definición de la GPIO que se va a utilizar, en este
caso la 2.
- Posteriormente se crea la función “hello_task”, la cual corresponde a una
de las tareas que se ejecutan. En esta tarea se está imprimiendo en pantalla
dentro de un ciclo infinito “Hello world!” cada 100 ms.
- De igual manera se crea la función “blinky”, es una de las tareas que se
ejecutan. En está tarea se selecciona la GPIO que se va a utilizar y se
dispone de esta como salida; en el ciclo infinito se está encendiendo y
apagando el led cada segundo.
- En la función principal “app_main()” se crean las dos tareas y se
configuran haciendo uso de la función “xTaskCreate”.
- xTaskCreate(): esta función se encarga de crear una tarea e igualmente la
añade a la lista de tareas que están listas para ejecutarse. Está función pide
para su funcionamiento los siguientes parámetros:
✓ pvTaskCode: puntero que llama a una tarea en específico con el
nombre que ha sido creada.
✓ pcName: nombre que se le asigna a la tarea con fines de identificarla y
facilitar la depuración, el nombre no puede exceder 16 caracteres.
✓ usStackDepth: tamaño asignado para el almacenamiento de pila de la
tarea, es decir la cantidad de variables que la tarea puede tener.
✓ pvParameters: para crear la tarea se utiliza este puntero como
parámetro que pasa a la tarea creada.
✓ uxPriority: Se le asigna una prioridad en la que se debe ejecutar una
tarea; si el número que se coloca es pequeño significa que tiene baja
prioridad la tarea, siendo 0 una tarea inactiva.
✓ pvCreatedTask: Se usa para pasar un identificador a la tarea creada
fuera de la función xTaskCreate(). pvCreatedTask es opcional y se
puede establecer en NULL.

• Resultados:
En la figura 1 podemos observar que se está imprimiendo constantemente
“Hello world!” a pesar de que se está ejecutando otra tarea al mismo tiempo.
Las dos tareas se están ejecutando con la misma prioridad y tanto la una como
la otra suceden en aproximadamente el tiempo configurado, es decir cada
segundo el led cambia de estado y cada 100 ms se está imprimiendo en
pantalla “Hello world!”.

Al observar las figuras 2 y 3 se puede evidenciar que la tarea “blinky” se está


ejecutando en el tiempo que se le asigno, por lo tanto, el led se enciende y
apaga en intervalos de 1 segundo. Por lo tanto, se puede concluir que las dos
tareas se están ejecutando simultáneamente y están ejecutándose en el tiempo
establecido.

Figura 1.
Figura 2.

Figura 3.
2. Tareas_Planificador:
• Código:
#include <driver/gpio.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <esp_system.h>
void tarea1(void *pvParameter)
{//Tarea que simula un pwm para observar en el analizador logico
while (1) // ciclo infinito
{
gpio_set_level(GPIO_NUM_2, 1); // Coloca en alto la GPIO2
ets_delay_us(25); // delay 25 us
gpio_set_level(GPIO_NUM_2, 0); // Coloca en bajo la GPIO2
ets_delay_us(25); // delay 25 us
}
}
void tarea2(void *pvParameter)
{//Tarea que simula un pwm para observar en el analizador logico
while (1) // ciclo infinito
{
gpio_set_level(GPIO_NUM_4, 1); // Coloca en alto la GPIO4
ets_delay_us(25); // delay 25 us
gpio_set_level(GPIO_NUM_4, 0); // Coloca en bajo la GPIO4
ets_delay_us(25); // delay 25 us
}
}
void tarea3(void *pvParameter)
{//Tarea que simula un pwm para observar en el analizador logico
while (1) // ciclo infinito
{
for (uint8_t i = 0; i < 200; i++) //se ejecuta 200 veces
{
gpio_set_level(GPIO_NUM_15, 1); // Coloca en alto la GPIO15
ets_delay_us(500); // delay 500 us
gpio_set_level(GPIO_NUM_15, 0); // Coloca en bajo la GPIO15
ets_delay_us(500); // delay 500 us
}
vTaskDelay(pdMS_TO_TICKS(200)); // Delay o bloqueo de la tarea
// de 200 ms
}
}

void app_main()
{
//Selección de los pines a utilizar
gpio_pad_select_gpio(GPIO_NUM_2);
gpio_pad_select_gpio(GPIO_NUM_4);
gpio_pad_select_gpio(GPIO_NUM_15);
//Configuración de los pines como salida
gpio_set_direction(GPIO_NUM_2, GPIO_MODE_OUTPUT);
gpio_set_direction(GPIO_NUM_4, GPIO_MODE_OUTPUT);
gpio_set_direction(GPIO_NUM_15, GPIO_MODE_OUTPUT);
//Creación de las tareas.
xTaskCreatePinnedToCore(tarea1, "task1", 2048, NULL, 1, NULL,
0);//Tarea 1 con prioridad (1) en el core 0
xTaskCreatePinnedToCore(tarea2, "task2", 2048, NULL, 1, NULL,
0);//Tarea 2 con prioridad (1) en el core 0
xTaskCreatePinnedToCore(tarea3, "task3", 2048, NULL, 2, NULL,
0);//Tarea 2 con prioridad (2) en el core 0
//xTaskCreatePinnedToCore(tarea3, "task3", 2048, NULL, 2, NULL,
1);//Tarea 2 con prioridad (2) en el core 1
}

• Explicación código:
- Se crean tres tareas las cuales únicamente cambian el estado de una GPIO
(diferente para cada tarea). Las tareas 1 y 2 son exactamente iguales,
cambian el estado de la GPIO 2 y 4, respectivamente, cada 25 us y se están
ejecutando con la misma cantidad de memoria y en el mismo núcleo. Por
otro lado, la tarea 3 cambia el estado de la GPIO 15 cada 500 us, pero está
se bloquea durante 200 milisegundos cada 200 ciclos; la tarea 3 tiene una
prioridad mayor a las otras dos y para verificar el funcionamiento de la
ESP32 se hacen dos experimentos: el primero ejecutándola en el núcleo 0
y el segundo en el núcleo 1.
- En la función principal se seleccionan los pines que se van a utilizar, estos
se configuran como salidas y se crean las tareas, pero a diferencia del
ejercicio anterior las tareas son creadas con la función
“xTaskCreatePinnedToCore”, la cual tiene un parámetro adicional donde
se selecciona en que núcleo se quiere ejecutar una tarea.
• Resultados:
- Todas las tareas en el mismo núcleo:
En la figura 4 se puede observar las gráficas de los pines 2 y 4, se puede
ver que las gráficas están casi superpuestas, por lo tanto, se están
ejecutando las tareas 1 y 2 casi simultáneamente, ya que estas dos tienen
el mismo valor de prioridad estas dos gráficas deben ser similares. Aun,
así como podemos ver en la figura 5 al ver más cerca, se está ejecutando
9ms una y 9ms la otra.
Como se puede observar en la figura 6 hay un intervalo de 200 ms en el
que la tarea 3 está bloqueada y como está tiene ua prioridad más alta,
mientras se está ejecutando las otras dos tareas no lo hacen. En la figura 7
se puede observar que aproximadamente el cambio de estado del pin 15 se
da cada 500 us, por lo tanto, la tarea 3 es la que se ejecuta con mayor
fidelidad dentro de los tiempos especificados cuando las tres tareas se
ejecutan en el mismo núcleo.
Figura 4. Pin 2 (Verde)y pin 4(azul)

Figura 5. Pin 2 (Verde)y pin 4(azul)


Figura 6. Pin2 (Verde) y pin15(azul)

Figura 7. Pin2 (Verde) y pin15(azul)


- Tareas 1 y 2 en el núcleo 0, tarea 3 en el núcleo 1:
En la figura 8 podemos observar que a diferencia cuando se ejecutaban las
3 tareas en el mismo núcleo (ver figura 4), las tareas 1 y 2 se están
ejecutando continuamente, es decir, ya no se bloquean 200 ms mientras se
está ejecutando la tarea 3. Como se observa en la figura 9, las tareas 1 y 2
no se están ejecutando completamente en paralelo, aunque tengan la
misma prioridad, aproximadamente se están ejecutando una después de la
otra en intervalos de 9 ms.
Como se observa en la figura 10, las tareas 1 y 3 se están ejecutando
completamente en paralelo y lo mismo sucedería si se compara la tarea 2
y 3; como las tareas 1 y 2 comparten el mismo núcleo y tienen la misma
prioridad no se ejecutan completamente en paralelo, primero se ejecuta
una cantidad de tiempo una y luego la otra (9 ms), pero como la tarea 3 se
está ejecutando completamente en un núcleo podemos decir que está se
está ejecutando con los tiempos definidos en la función “tarea3”. En
conclusión, cuando una tarea se ejecuta en un núcleo diferente, está no
influye en el tiempo de ejecución de la o las otras tareas que se ejecuten
en el otro núcleo.
Por último, como se puede observar en la figura 11, el cambio de estado
del pin 15 en la tarea 3 se da aproximadamente a los 500 us, se puede
inferir que debido a la prioridad que tiene y a que se está ejecutando en un
núcleo independiente los tiempos entre cada cambio de estado definidos
con los delays se están cumpliendo.
Figura 8. Pin 2()verde, pin 4(azul)

Figura 9. Pin 2()verde, pin 4(azul)


Figura 10. Pin 2 (verde), pin15 (azul)

Figura 11. Pin 15

También podría gustarte