Ir a contenido
Introducción a los SO en tiempo real: conociendo FreeRTOS - 330ohms

Introducción a los SO en tiempo real: conociendo FreeRTOS - 330ohms

En esta entrada nos vamos a familiarizar con FreeRTOS y su código fuente. Aprenderemos cómo se implementa en el ESP32 con el IDE de Arduino. Para empezar, vamos a la página oficial de FreeRTOS y descargamos el código desde Downloads. Mientras que se descarga el archivo, podemos ver las secciones de kernel, libraries y resources para entender como implementar el SO en otro dispositivo. Cuando tengamos el archivo podemos ver su contenido y observamos las distintas carpetas que contienen los ejemplos, las librerías y el código base.

Pero en este tutorial nos centraremos en la versión modificada para ESP32 y por lo tanto podemos consultar los cambios hechos al código fuente original de FreeRTOS para adaptarlo a la ESP32.

Instalando la ESP32 en el IDE de Arduino

Para que nuestra ESP32 funcione en el IDE de Arduino y podamos programarla es necesario agregarla al administrador de tarjetas. Para ello vamos a añadir en el repositorio el enlace del distribuidor de la tarjeta. Abrimos el IDE de Arduino y nos vamos a la sección de Archivo>Preferencias y añadimos este enlace: https://dl.espressif.com/dl/package_esp32_index.json a las URL adicionales.

Ahora nos vamos al administrador de tarjetas desde Herramientas>Placa>Gestor de Tarjetas y buscamos la ESP32, encontramos la tarjeta y la instalamos en nuestro IDE. Con esto podremos cargar nuestros programas a la tarjeta y trabajar con la versión modificada de FreeRTOS.

Desarrollo del programa

Como primer ejercicio vamos a desarrollar un programa “Blink” usando las funciones propias de FreeRTOS. La codificación puede parecer un poco excesiva para algo simple como parpadear un LED pero nos va a familiarizar con los elementos básicos del sistema y nos permitirá desarrollar ejercicios más complejos después.

Lo primero que debemos hacer es definir ciertas constantes para indicarle al programa que procesador vamos a usar, si el 0 o el 1 y el LED que vamos a parpadear, que será el LED integrado. Para ello, dependiendo de las librerías del programa, definimos app_cpu como el procesador 0 o 1 y definimos la constante led_pin como el LED a parpadear

//use only core 1 for demo purpouses #if CONFIG_FREERTOS_UNICORE static const BaseType_t app_cpu = 0; #else static const BaseType_t app_cpu = 1; #endif  //Pins static const int led_pin = LED_BUILTIN;

Después definimos la función que haremos llamar para parpadear el LED, que en otras palabras será nuestra Tarea 1 o “Task 1”. Una función que no regrese parámetros con funciones vTaskDelay() y digitalWrite() será suficiente. Observen que en este caso usamos vTaskDelay y no solamente delay(). Esto se debe a que es una función de FreeRTOS que sirve de retardo para cada Tarea.

//Our task: blink an LED void toggleLED(void *parameter){   while(1){     digitalWrite(led_pin,HIGH);     vTaskDelay(500 / portTICK_PERIOD_MS);     digitalWrite(led_pin,LOW);     vTaskDelay(500 / portTICK_PERIOD_MS);   } }

Por ultimo, vamos a crear la función de configuración en donde asignamos el tipo de pin al LED y configuramos los parámetros de nuestra tarea formalmente. Le asignamos a la tarea una función, un nombre, la cantidad de memoria que puede usar, un apuntador, la prioridad de la tarea, otro apuntador que nos permite manejar la tarea y el núcleo o procesador que vamos a usar. En función loop() no necesitamos agregar nada.

void setup() {   //Configure pins   pinMode(led_pin, OUTPUT);    //task to run forever   xTaskCreatePinnedToCore(             toggleLED,        //Funcion a llamar             "Toggle LED",     //Nombre de la tarea             1024,             //Bytes de memoria que puede usar la tarea             NULL,             //Apuntador de memoria (no se usa)             1,                //Prioridad de la tarea (de 0 a 24, siendo 24 la mayor prioridad)             NULL,             //Apuntador de tarea             app_cpu);         //Nucleo o procesador que vamos a usar  }  void loop() {   // put your main code here, to run repeatedly:  }

Si todo salió correctamente deberías ver tu LED integrado parpadeando a 1Hz. Si quieres copiar y pegar el códuigo completo puedes revisar el final de esta entrada.

Conclusiones:

Hemos creado nuestro primer código de FreeRTOS y nos hemos familiarizado con las funciones que permiten crear las tareas y los parámetros con las que se configuran. Nuestro siguiente ejercicio sería crear una nueva tarea que se ejecute de forma paralela y que tenga un delay distinto los 500ms, esto creará un efecto de parpadeo distinto y controlará al LED de forma simultánea.

Código:

//use only core 1 for demo purpouses #if CONFIG_FREERTOS_UNICORE static const BaseType_t app_cpu = 0; #else static const BaseType_t app_cpu = 1; #endif  //Pins static const int led_pin = LED_BUILTIN;  //Our task: blink an LED void toggleLED(void *parameter){   while(1){     digitalWrite(led_pin,HIGH);     vTaskDelay(500 / portTICK_PERIOD_MS);     digitalWrite(led_pin,LOW);     vTaskDelay(500 / portTICK_PERIOD_MS);   } } void setup() {   //Configure pins   pinMode(led_pin, OUTPUT);    //task to run forever   xTaskCreatePinnedToCore(             toggleLED,        //Funcion a llamar             "Toggle LED",     //Nombre de la tarea             1024,             //Bytes de memoria que puede usar la tarea             NULL,             //Apuntador de memoria (no se usa)             1,                //Prioridad de la tarea (de 0 a 24, siendo 24 la mayor prioridad)             NULL,             //Apuntador de tarea             app_cpu);         //Nucleo o procesador que vamos a usar  }  void loop() {   // put your main code here, to run repeatedly:  }

Referencias:

Introduction to RTOS Part 2 – Getting Started with FreeRTOS | Digi-Key Electronics

Artículo anterior Tutorial #8 de Raspberry Pi Pico: sensor ultrasónico - 330ohms