Victor Armando Avendaño Osorio
Neftali Larios
Excelente aporte porque como lo hizo Diana no veia los mensajes de suspender, resumen y borrar, con tu codigo lo pude ver. Gracias.
La razón por la que los logs del ejemplo al final, no salen intercalados uno a uno de forma ideal, es porque en la práctica FreeRTOS le asigna un tiempo fijo a cada tarea, por lo que mientras la tarea siga dentro de su tiempo disponible, seguirá ejecutando los printf que le corresponden, hasta que FreeRTOS le de paso a la siguiente.
Es por eso que vemos varios "Task 1" juntos, luego varios "Task 2" juntos, y así sucesivamente.
Victor Armando Avendaño Osorio
Neftali Larios
Excelente aporte porque como lo hizo Diana no veia los mensajes de suspender, resumen y borrar, con tu codigo lo pude ver. Gracias.
Julio Cardenas
Ciclo de vida de las tareas con FreeRTOS
Luis Enrique Carreño Herreño
ALEJANDRO OLGUIN
Gracias !
Rogelio Meza
En la esp32 CAM me paso exactamente lo mismo y de igual forma se arreglo solo con la linea vTaskDelay(pdMS_TO_TICKS(100));
Muchisimas gracias c:
Mariana Valencia Gallego
En mi vida soy el core 1 entrando en pánico ;')
Luis Ariel Torres
Si task1 se ejecuta en el core 0 y task2 en el 1. ¿Cómo se arreglan los dos cores para compartir un recurso unico como es la UART?
Diana Martinez
Todo eso lo coordina el sistema operativo, justo el trabajo de un sistema operativo es administrar los recursos, y pues del mismo modo que con las tareas, se pausa una y se permite la otra, o se puede tener una tarea dedicada (que también se pausará), pero en lugar de leer directamente al hardware, las demás intercambiarán mensajes con la única tarea que si lo hace.
Diana Martinez
Con un FreeRTOS limpio (no el modificado por ESP-IDF), podrías configurar todos los parámetros de comportamiento del RTOS a tu gusto, pero en este caso se podrían configurar algunas cosas con el menuconfig.
Andres Esteban Andrews Castillo
¿cómo puedo detener el ciclo infinito desde la terminar? para no tener que cerrar y volver a abirla.
Diana Martinez
En windows es Ctrl + ]
Jesús Ramon
y en linux?
Juan Sebatian Ariza
Diana Martinez
Creo que podría estarte faltando un delay o un delete, porque al parecer se está reiniciando tu aplicación, y eso pasa principalmente cuando una tarea se queda con todos los recursos y el kernel tiene que sacarla de ahí.
Daniel Lopez Piña
Sigo teniendo el mismo problema, ya puse los delay y se me cicla la salida.
Andrés González
No logré que se ejecutaran en paralelo no lo sé
#include <stdio.h>#include "freertos/FreeRTOS.h"#include "freertos/task.h" TaskHandle_t taskHandle1 = NULL;TaskHandle_t taskHandle2 = NULL; void task1(void *args){ int count = 0; while(1){ count++; printf("Task #1; count: %d\n", count); if(count == 3 && taskHandle2 != NULL){ vTaskSuspend(taskHandle2); printf("Task #2 suspend\n"); } if(count == 10 && taskHandle2 != NULL){ vTaskResume(taskHandle2); printf("Task #2 resume\n"); } if(count == 12 && taskHandle2 != NULL){ vTaskDelete(taskHandle2); printf("Task #2 delete\n"); } if(count >= 15){ printf("Task #1 Ok\n"); vTaskDelete(NULL); } }} void task2(void *args){ int count = 0; while(1){ count++; printf("Task #2; count: %d\n", count); if(count >= 15){ vTaskDelete(NULL); } }} void app_main(void){ // Parametros: // función, // nombre de la tarea, // espacio reservado en memoria, // datos iniciales de la tarea, // prioridad de la tarea, // Almacenar la tarea para manipularla, // # de Core xTaskCreate(task1, "task1", 4096, NULL, 10, &taskHandle1); // Core 0 por defecto xTaskCreatePinnedToCore(task2, "task2", 4096, NULL, 10, &taskHandle2, 1);}
Gabriel Obregón
eRTOS
Manejo de Tareas en FreeRTOS con ESP32
En este documento, exploraremos cómo crear, pausar, reanudar y eliminar tareas en FreeRTOS utilizando un ESP32. También veremos cómo asignar tareas a diferentes núcleos del procesador y corregiremos errores comunes para evitar reinicios inesperados.
1. Creación de Tareas
Para iniciar, creamos una tarea simple que cuenta hasta 5 antes de eliminarse:
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
TaskHandle_t taskHandle1 = NULL;
void task1(void *args) {
int count = 0;
while (1) {
count++;
printf("Task 1 count: %d\n", count);
if (count > 5) {
vTaskDelete(NULL);
}
}
}
void app_main(void)
{
xTaskCreate(task1, "task1", 4096, NULL, 10, &taskHandle1);
}
Este código crea una tarea que se ejecuta en un bucle hasta que count supera 5, momento en el cual se elimina.
2. Creación de una Segunda Tarea
Para agregar una segunda tarea, modificamos el código para incluir task2:
TaskHandle_t taskHandle2 = NULL;
void task2(void *args) {
int count = 0;
while (1) {
count++;
printf("Task 2 count: %d\n", count);
}
}
void app_main(void)
{
xTaskCreate(task1, "task1", 4096, NULL, 10, &taskHandle1);
xTaskCreate(task2, "task2", 4096, NULL, 10, &taskHandle2);
}
Ahora, tenemos dos tareas ejecutándose en paralelo con la misma prioridad.
3. Asignación de Tareas a Diferentes Núcleos
Podemos ejecutar task2 en el segundo núcleo del ESP32 utilizando xTaskCreatePinnedToCore:
void app_main(void)
{
xTaskCreate(task1, "task1", 4096, NULL, 10, &taskHandle1);
xTaskCreatePinnedToCore(task2, "task2", 4096, NULL, 10, &taskHandle2, 1);
}
De esta manera, task1 se ejecuta en el núcleo 0 y task2 en el núcleo 1.
4. Control de Ejecución de Tareas
Ahora, task1 controlará la ejecución de task2. La lógica es la siguiente:
Código actualizado:
void task1(void *args) {
int count = 0;
while (1) {
count++;
printf("Task 1 count: %d\n", count);
if (count == 3) {
vTaskSuspend(taskHandle2);
printf("Task 2 suspended\n");
}
if (count == 10) {
vTaskResume(taskHandle2);
printf("Task 2 resumed\n");
}
if (count == 12) {
vTaskDelete(taskHandle2);
printf("Task 2 deleted\n");
}
if (count == 15) {
printf("Task 1 deleted\n");
vTaskDelete(NULL);
}
}
}
Este código permite que task1 gestione task2 de manera controlada.
5. Compilación y Ejecución
Para compilar y subir el código al ESP32, ejecutamos en la terminal:
idf.py build
idf.py -p COM3 flash
idf.py -p COM3 monitor
Observaremos la ejecución en el monitor serie, donde task1 contará y suspenderá, reanudará y eliminará task2 en los momentos adecuados.
6. Consideraciones Finales
Este ejercicio nos ayuda a comprender cómo FreeRTOS maneja tareas y cómo podemos controlarlas eficientemente.
Julio Cardenas
Ahí os dejo mi código
#include <stdio.h> #include "esp_chip_info.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" TaskHandle_t task1Handle = NULL; TaskHandle_t task1Handle2 = NULL; void task1(void *arg){ unsigned int counter = 0; while(1){ printf("Tarea 1, felicidades, count: %d\n", counter); counter++; if(counter == 5){ printf("tarea 2 suspendida\n"); vTaskSuspend(task1Handle2); } if (counter == 10){ printf("tarea 2 reanudada\n"); vTaskResume(task1Handle2); } if (counter == 15){ printf("tarea 2 eliminada\n"); vTaskDelete(task1Handle2); } if (counter == 15){ printf("tarea 1 finalizada\n"); vTaskDelete(NULL); } vTaskDelay(100 / portTICK_PERIOD_MS); } } void task2(void *arg){ unsigned int counter = 0; while(1){ printf("Tarea 2, felicidades, count: %d\n", counter); counter++; if (counter>15){ printf("tarea 2 finalizada\n"); vTaskDelete(NULL); } vTaskDelay(100 / portTICK_PERIOD_MS); } } void app_main(void) { xTaskCreatePinnedToCore(task1, "task1", 4096, NULL, 10, &task1Handle, 0); xTaskCreatePinnedToCore(task2, "task2", 4096, NULL, 10, &task1Handle2, 1); }
Le puse un pequeño delay de 100ms porque sin eso algunos printf no salían y parecía que en el tiempo en el que se montaba la tarea 2 en el segundo núcleo le daba tiempo la la tarea 1 de ejecutarse en su totalidad y los log salían muy raro.
Estoy probando con el LilyGo TTGO LoRa 32, y obtenía la salida:
I (313) app_start: Starting scheduler on CPU0 I (318) app_start: Starting scheduler on CPU1 I (318) main_task: Started on CPU0 I (328) main_task: Calling app_main() Task 1 count: 1 Task 1 count: 2 Task 1 count: 3 Task 2 suspended I (328) main_task: Returned from app_main() Task 2 count: 1 Task 2 count: 2 Task 2 count: 3 Task 2 count: 4 Task 2 count: 5 Task 2 count: 6 Task 2 count: 7 Task 2 count: 8 Task 2 count: 9 Task 2 count: 10 Task 2 count: 11 Task 2 count: 12 Task 2 count: 13 Task 2 count: 14 Task 2 count: 15 Task 2 deleted
No se ve que la tarea 1 no controla la tarea. 2, ya que se la tarea 2 sigue ejecutándose después de que la tarea 1 la suspende, así que agregué al final del while de cada tarea un delay:
while (1) { ... vTaskDelay(pdMS_TO_TICKS(100)); }
Y de esa forma ya funciona como debe:
I (313) app_start: Starting scheduler on CPU0 I (318) app_start: Starting scheduler on CPU1 I (318) main_task: Started on CPU0 I (328) main_task: Calling app_main() Task 1 count: 1 I (328) main_task: Returned from app_main() Task 2 count: 1 Task 1 count: 2 Task 2 count: 2 Task 1 count: 3 Task 2 suspended Task 1 count: 4 Task 1 count: 5 Task 1 count: 6 Task 1 count: 7 Task 1 count: 8 Task 1 count: 9 Task 1 count: 10 Task 2 resumed Task 2 count: 3 Task 1 count: 11 Task 2 count: 4 Task 1 count: 12 Task 2 deleted Task 1 count: 13 Task 1 count: 14 Task 1 count: 15 Task 1 deleted
tengo una duda, no he logrado hacer que corra dos treas al tiempo, es muy curioso que cuando el conntador llega a 3 es cuando empieza la tarea 2, no se si sera un problema de mi placa o que pueda estr sucediendo.
esta es la salida que obtengo con el monitor:
Task 1 count: 1 Task 1 count: 2 Task 1 count: 3 Task 2 suspend I (332) main_task: Returned from app_main() Task 2 count: 1 Task 2 count: 2 Task 2 count: 3 Task 2 count: 4 Task 2 count: 5 Task 2 count: 6 Task 2 count: 7 Task 2 count: 8 Task 2 count: 9 Task 2 count: 10 Task 2 count: 11 Task 2 count: 12 Task 2 count: 13 Task 2 count: 14 Task 2 count: 15
Este es mi codigo utilizando vTaskDelay
#include <stdio.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "time.h" TaskHandle_t taskHandle_1; TaskHandle_t taskHandle_2; const TickType_t taskDelay_1 = 500 / portTICK_PERIOD_MS; const TickType_t taskDelay_2 = 700 / portTICK_PERIOD_MS; time_t elapsed_time_1; time_t elapsed_time_2; int counter_1 = 0; int counter_2 = 0; void task_1(void *args) { while (true) { time(&elapsed_time_1); printf("Task 1 counter: %d seconds: %lld\n", counter_1, elapsed_time_1); counter_1++; vTaskDelay(taskDelay_1); switch (counter_1) { case 10: printf("Suspendiendo la tarea 2\n"); vTaskSuspend(taskHandle_2); break; case 20: printf("Resumiendo la tarea 2\n"); vTaskResume(taskHandle_2); break; case 30: printf("Eliminando la tarea 2\n"); vTaskDelete(taskHandle_2); break; case 50 ... 60: printf("Eliminando la tarea 1\n"); vTaskDelete(taskHandle_1); break; default: break; }; } } void task_2(void *args) { while (true) { time(&elapsed_time_2); printf("Task 2 counter: %d seconds: %lld\n", counter_2, elapsed_time_2); counter_2++; vTaskDelay(taskDelay_2); if (counter_2 > 50) { printf("Finalizando la tarea 2\n"); vTaskDelete(taskHandle_2); } } } void app_main(void) { xTaskCreate( task_1, //Nombre de la funcion que implementa la tarea "Tarea_1", //Nombre descriptivo de la tarea con fines de debugging 4096, //El tamaño del task stack en bytes NULL, //pointer a un parametro cuando la tarea esta siendo creada 10, //Prioridad de la tarea un numero &taskHandle_1 //apuntador para referenciar la tarea. ); //creamos la tarea asociandola al segundo core xTaskCreatePinnedToCore( task_2, //Nombre de la funcion que implementa la tarea "Tarea_2", //Nombre descriptivo de la tarea con fines de debugging 4096, //El tamaño del task stack en bytes NULL, //pointer a un parametro cuando la tarea esta siendo creada 10, //Prioridad de la tarea un numero &taskHandle_2, //apuntador para referenciar la tarea. 1 // core 0 y core 1 ); }