Tabla de Contenidos

Descripción

FreeRTOS es un sistema operativo de tiempo real multitareas el cual permite administrar los recursos hardware y los tiempos de ejecución de las diferentes tareas implementadas en un microcontrolador. FreeRTOS está desarrollado en lenguaje ANSI-C, conformado por un conjunto de funciones que se ejecutan en momentos determinados del programa y distribuido gratuitamente bajo licencia “Open Source”, incluyendo aplicaciones comerciales.

Actualmente FreeRTOS tiene puertos para procesadores, microcontroladores y softcore de diferentes arquitecturas y marcas. Un listado oficial de los diferentes puertos soportados de manera oficial puede encontrarse en el siguiente enlace: http://www.freertos.org/RTOS_ports.html

Es el interés de esta guía es entregar los fundamentos de sistemas operativos de tiempo real, basados en ejemplos e información propia para FreeRTOS.

Lecturas de interés

Fundamentos de sistemas operativos de tiempo real RTOS

El kernel es el componente principal en un sistema operativo. Cada programa que se ejecuta en una aplicación corresponde a una tarea que está bajo el control del sistema operativo. Si el sistema operativo permite ejecutar multiples tareas, se dice que es un sistema operativo multitareas.

Tiempo real en los sistemas operativos

Las soluciones desarrolladas típicamente en un microcontrolador tienen requerimientos de tiempo real, esto implica que, los tiempos en los que se ejecutan las tareas deben ser determinísticos y por ello es necesario administrar de forma correcta los recursos de control de tiempo como temporizadores para poder atender todos los eventos que puedan presentarse durante la ejecución del sistema electrónico. Los requerimientos de tiempo real pueden ser “Soft Real Time” y “Hard Real Time”.

Multitarea vs Concurrencia

En un procesador de un solo nucleo solo se puede ejecutar una tarea al tiempo, pero, se realizan cambios de contexto entre tareas que permiten dar la apariencia que todas las tareas se estan ejecutando de forma concurrente (ejecución simultanea).

Introducción a FreeRTOS

Tareas

Una tarea es un programa independiente que desarrolla operaciones específicas utilizando uno o varios recursos del microcontrolador como UART, SPI, I2C, memoria RAM, CPU, etc. En una aplicación con sistemas operativos bajo en contexto de multitareas, son varios programas los que comparten los recursos hardware del microcontrolador, incluyendo la CPU. Cada tarea se ejecuta solo cuando todos los argumentos y recursos están disponibles, de lo contrario dicha tarea no podra ser ejecutada por la CPU.

Estructura en lenguaje C de una tarea en FreeRTOS

En FreeRTOS, las tareas tienen una estructura predefinida

void ATaskFunction( void *pvParameters )
{
/* Declara variables locales que utiliza la tarea*/
int iVariableExample = 0;
 
/* La tarea es definida dentro de un ciclo infinito. */
for( ;; )
{
/* El código que ejecuta la tarea está dentro del ciclo infinito. */
}
/* Si la terea sale del ciclo infinito, se entiende que finaliza las operaciones de la misma, por ello esta debe borrarse 
con la funcion de FreeRTOS vTaskDelete(). 
Esto libera todos los recursos que utilizaba dicha tarea. */
vTaskDelete( NULL );
}

Estados de una tarea en FreeRTOS

Una aplicación consiste de muchas tarea. En un microcontrolador con una CPU solo puede ejecutar una tarea a la vez y es deber del sistema operativo gestionar el recurso compartido (CPU) para lograr que todas las tareas sean ejecutadas dentro de unas restricciones de tiempo predefinidas. Si el microcontrolador cuenta con dos o más nucles de procesamiento, serán dos o más las tareas que puedan ejecutarse al tiempo, siempre y cuando todos los argumentos y recursos necesitados por cada tarea estén disponibles.

En el caso de un microcontrolador con una CPU, solo una tarea puede estar en estado “Running”, todas las demás tareas pueden permanecer en estados validos “Suspended”, “Ready” o “Blocked”.

Estados de una tarea y sus transiciones validas Estados de una tarea y sus transiciones validas

El “scheduler” entrega la CPU (pasar a estado “running”) a una de todas las tareas que se encuentren en estado “ready”. La decisión de a cual tarea entregar la CPU va a depender de las politicas de planificación seleccionada para el “scheduler”. Si varias tareas estan en estado ready, siempre la que tenga mayor prioridad será la que pase primero a estado “running”.

Prioridades de una tarea en FreeRTOS

Cada tarea tiene una prioridad que es asignada en el momento de ser creada. En FreeRTOS una prioridad representada con un número de bajo peso, representa una prioridad baja. Para FreeRTOS existe una tarea denominada “idle task ” y tiene prioridad cero (tskIDLE_PRIORITY). El valor máximo que puede asignarse a una prioridad va a depender del puerto para el cual se está desarrollando la aplicación con FreeRTOS y de su configuración que se encuentra en el archivo “FreeRTOSConfig.h”. El valor en “configMAX_PRIORITIES” define la prioridad máxima para el puerto específico.

Varias tareas pueden tener la misma prioridad y dependiendo de las politicas de operación del scheduler, le será asignado el uso de la CPU a una tarea en específico. En caso de ser habilitado configUSE_TIME_SLICING y son varias tareas con la misma prioridad en estado “ready”, la CPU le será asigna una a una por un espacio de tiempo, a lo cual se llama esquema de planificación “round robin”. Si no es habilitado configUSE_TIME_SLICING y son varias tareas con la misma prioridad en estado “ready”, la CPU le será asignada a la primera tarea en llegar a estado ready y solo cuando esta tarea decida ceder la CPU, se revisará nuevamente las prioridades de las tareas que siguen en estado ready, a lo cual se llama esquema de planificación FIFO.

La prioridad de una tarea puede cambiar en tiempo de ejecución

Tarea Idle en FreeRTOS

Es una tarea creada de manera automática cuando el “scheduler” del RTOS es iniciado. El scheduler debe tener siempre al menos una tarea en estado ready, y para este propósito es la tarea “idle”. Con la prioridad más baja posible (tskIDLE_PRIORITY) se asegura que las demás tareas de la aplicación tengan la CPU cuando esten listas para su ejecución. Esta tarea también cumple la función de liberar la memoria asignada por el RTOS a aquellas tareas que ya han sido eliminadas.

Algunas tareas pueden compartir la misma prioridad de la tarea idle y si este es el caso, se deben revisar las políticas de operación del scheduler para la ejecución de tareas de igual prioridad.

Creación de tareas en FreeRTOS

Una tarea de crea usando la función API de FreeRTOS xTaskCreate(). Es una de las funciones más complejas de FreeRTOS por la cantidad de parámetros que deben ser entregados para su ejecución.

portBASE_TYPE xTaskCreate( pdTASK_CODE pvTaskCode,
const signed portCHAR * const pcName,
unsigned portSHORT usStackDepth,
void *pvParameters,
unsigned portBASE_TYPE uxPriority,
xTaskHandle *pxCreatedTask
);

Anatomía de un proyecto con FreeRTOS

FreeRTOS suministra todas las funciones para la implementación del sistema operativo, incluyendo ejemplos para diferentes puertos. Los archivos mínimos que deben estar presentes en un proyecto con FreeRTOS son:

Si se necesita la funcionalidad timer, incluir “FreeRTOS/Source/timers.c”

Si se necesita la funcionalidad co-routines, incluir “FreeRTOS/Source/croutine.c”

El compilador utilizado debe incluir las siguientes rutas en disco para la busqueda de las fuentes del FreeRTOS:

Personalización y configuraciones en FreeRTOS

FreeRTOS centra todas las configuraciones en un archivo con nombre “FreeRTOSConfig.h”. Es en este archivo donde se puede escalar el sistema operativo, habilitando o deshabilitando funciones para con ello lograr una solución más robusta donde se ocupa mayor cantidad de memoria FLASH y RAM o una solución más ligera, en la que solo aquellos servicios requeridos son incorporados durante la compilación de la aplicación.

El contenido típico del archivo “FreeRTOSConfig.h”:

Para conocer con detalle cada una de las características del FreeRTOS que pueden ser configuradas desde FreeRTOSConfig.h, leer el Manual de Referencia FreeRTOS V9.0.0

#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
 
/* 
 * The following #error directive is to remind users that a batch file must be
 * executed prior to this project being built.  The batch file *cannot* be 
 * executed from within the IDE!  Once it has been executed, re-open or refresh 
 * the Eclipse project and remove the #error line below.
 */
 
#include "system.h"
 
/*-----------------------------------------------------------
 * Application specific definitions.
 *
 * These definitions should be adjusted for your particular hardware and
 * application requirements.
 *
 * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
 * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. 
 *----------------------------------------------------------*/
 
#define configUSE_PREEMPTION        1
#define configUSE_IDLE_HOOK         0
#define configUSE_TICK_HOOK         0
#define configTICK_RATE_HZ       ( ( TickType_t ) 1000 )
#define configCPU_CLOCK_HZ       ( ( unsigned long ) SYS_CLK_FREQ )  
#define configMAX_PRIORITIES        ( 5 )
#define configMINIMAL_STACK_SIZE    ( 1024 )
#define configISR_STACK_SIZE        configMINIMAL_STACK_SIZE
#define configTOTAL_HEAP_SIZE       ( ( size_t ) 8388608 )
#define configMAX_TASK_NAME_LEN        ( 8 )
#define configUSE_TRACE_FACILITY    0
#define configUSE_16_BIT_TICKS         0
#define configIDLE_SHOULD_YIELD        0
#define configUSE_MUTEXES        1
#define configUSE_RECURSIVE_MUTEXES    1
#define configUSE_COUNTING_SEMAPHORES     1
#define configCHECK_FOR_STACK_OVERFLOW    0
#define configQUEUE_REGISTRY_SIZE      0
 
/* Co-routine definitions. */
#define configUSE_CO_ROUTINES          0
#define configMAX_CO_ROUTINE_PRIORITIES   ( 2 )
 
/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */
 
#define INCLUDE_vTaskPrioritySet    1
#define INCLUDE_uxTaskPriorityGet      1
#define INCLUDE_vTaskDelete         1
#define INCLUDE_vTaskCleanUpResources     0
#define INCLUDE_vTaskSuspend        1
#define INCLUDE_vTaskDelayUntil        1
#define INCLUDE_vTaskDelay       1
#define INCLUDE_uxTaskGetStackHighWaterMark  1
 
/* The priority at which the tick interrupt runs.  This should probably be
kept at 1. */
#define configKERNEL_INTERRUPT_PRIORITY      0x01
 
/* The maximum interrupt priority from which FreeRTOS.org API functions can
be called.  Only API functions that end in ...FromISR() can be used within
interrupts. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 0x03
 
#endif /* FREERTOS_CONFIG_H */

Proyectos