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

Anuncio
RaspberryPi

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.

Anuncio
RaspberryPi

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