FreeRTOS
|
FreeRTOS
FreeRTOS porta todas sus funcionalidades oficialmente hasta 27 arquitecturas y se le hacen más de 77,500 descargas anualmente. Se libera bajo la licencia libre GPLv2 con una enmienda especial de poder utilizar código propietario sin que este sea liberado. Se integra fácilmente con otras bibliotecas libres para el manejo de periféricos y puertos como son: FatFS un manejador del sistema de archivo FAT para sistemas empotrados, lwIP una pila TCP/IP ligera, controladores para el manejo de puertos USB, entre otros. Se integra además con diversos IDE para el manejo de funciones de programación y depuración como son Eclipse y MPLAB.
Características
El planificador ofrece una serie de funcionalidades consideradas obligatorias en el diseño de sistemas operativos de tiempo real. Ligado esto al hecho de que FreeRTOS lo componen 4 archivos de código fuente, hacen que sea tanto simple como eficiente:
- Funcionamiento apropiable o cooperativo.
- Asignación de prioridades a las tareas de una forma flexible.
- Manejo de colas, utilizadas para el paso de mensajes entre tareas.
- Uso de semáforos binarios, recursivos, de conteo y de exclusión mutua.
- Funciones para distintos estados del planificador: tick del reloj, inactividad, chequeo de desbordamiento de pila.
- Macros para el monitoreo de parámetros de ejecución.
- Soporte y licenciamiento comercial opcional.
Está escrito mayoritariamente en C salvo en secciones específicas a cada arquitectura donde es necesario el uso de ensamblador. Se emplea en microcontroladores de limitados y medianos recursos, entre 32 KB y 512 KB de memoria Flash y 16 KB y 256 KB de memoria RAM. Aunque se ha probado en microcontroladores de 8 KB de RAM. Generalmente un binario ya compilado se llevará entre 4 KB y 9 KB.
Código
Ejemplos de funciones utilizadas dentro de freeRTOS que generalmente se utilizan también en entornos de mayor nivel o con lenguajes de programación más robustos.
Crear una tarea
xTaskCreate( configTask, ( signed portCHAR * ) "configTask", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); ... void configTask( void* p ) { }
El primer parámetro configTask especifica la función que contendrá el cuerpo de la tarea, el segundo parámetro un identificador para la tarea, el tercer parámetro el tamaño de la pila configMINIMAL_STACK_SIZE es el mínimo en este caso, el cuarto es un puntero a los parámetros que le pasaremos a la tarea, en este caso ninguno, el quinto parámetro especifica la prioridad de la tarea el cual está en el mínimo tskIDLE_PRIORITY y por último se pasa por parámetro el manejador de la tarea que en este caso no se especifica.
Crear y utilizar un semáforo
xSemaphoreHandle atdMonitor = xSemaphoreCreateMutex(); if( xSemaphoreTake( atdMonitor, portMAX_DELAY ) == pdTRUE ) { // Algo aquí xSemaphoreGive( atdMonitor ); }
Se crea primero un semáforo de tipo exclusión mutua con xSemaphoreCreateMutex() y luego para apropiarse del semáforo, se invoca a xSemaphoreTake() pasando por parámetros el semáforo y la demora a esperar a que se obtenga, en este caso se pide bloquear hasta que se libere. Por último se libera el semáforo dentro del contexto de ejecución de la función con xSemaphoreGive().
Crear y utilizar una cola de mensajes
xQueueHandle handleUp = xQueueCreate( 128, sizeof( char ) ); ... char c = 'a'; xQueueSend( handleUp, (void*) &c, 10 ); ... char d; xQueueReceive( handleUp, &d, 10 );
En el ejemplo se crea una cola llamada handleUp con la función xQueueCreate(). Más adelante se envia un caracter a la cola con xQueueSend(). Por parámetros le especificamos la cola a utilizar, el caracter y el tiempo de espera de confirmación de envio. En otra sección de código se recibe el caracter con la función xQueueReceive(). Los parámetros aquí son análogos a los de la función anterior.