Ir al contenido principal

Modelos y frameworks en embedded software de manera simple - Parte III "Framework RKH"

La presente publicación es la tercera y última parte del artículo "Modelos y frameworks en embedded software de manera simple", que explora las características y los beneficios de utilizar modelos y frameworks para disminuir el costo, la complejidad y el tiempo de desarrollo del software de un embedded system. Esta última parte presenta y describe el framework RKH de Vortex, sus servicios, principales características, las ventajas de su uso y su estructura interna.

Parte 1: "Modelos y frameworks en embedded software de manera simple - Usando modelos"
Parte 2: "Modelos y frameworks en embedded software de manera simple - Usando frameworks"

¿Qué es RKH?

Es un paquete de software multiplataforma que provee un conjunto de servicios comunes y fundamentales entre aplicaciones del mismo dominio, en especial los embedded systems, cuyo objetivo es facilitar el desarrollo de sistemas parcialmente o totalmente reactivos, en los cuales su comportamiento dinámico se representa mediante máquinas de estados planas y/o Statecharts, incluyendo aquellos con restricciones temporales o real-time dentro de un marco formal, simple, bien definido y estructurado.

RKH permite construir de manera rápida y segura aplicaciones completas desde el origen o acoplarse a una aplicación funcional existente, incluyendo una no necesariamente reactiva, y trabajar en colaboración.

El framework RKH es la parte de la aplicación que provee la infraestructura necesaria para construir embedded software bajo el paradigma de la programación dirigida por eventos, basado en la ejecución simultánea de máquinas de estados del tipo Statecharts, de acuerdo con UML 2.x.

Sus servicios

No sólo soporta la implementación de múltiples Statecharts en ejecución simultánea, sino también provee los servicios necesarios para tal fin como el administrador de eventos, cola de eventos, objetos activos, temporizadores, gestor de asignación dinámica de memoria, trazador para la verificación, validación y depuración durante su ejecución, ambiente para la prueba unitaria de máquinas de estados, entre otros.

La asignación dinámica de memoria, se realiza bajo el patrón de bloques de tamaño fijo, el cual evita la fragmentación y el no-determinismo de la asignación dinámica tradicional.

Sus características

Implementación del modelo Statechart

  • Tanto la semántica como la sintaxis de los Statecharts se basa en la especificación de OMG UML 2.x. Básicamente soporta:
    • Pseudo-estados junction, branch, history (shallow y deep).
    • Transiciones compuestas y condicionales.
    • Estados submachine.
    • Acciones de inicialización por defecto, entrada y salida de estados.
    • Secuencia tradicional en la ejecución de una transición.
    • Mecanismo para eventos diferidos.
    • Transiciones locales, internas y de terminación.
    • Estado final.
  • La codificación de los Statecharts es simple e intuitiva. El código refleja lo que el modelo indica sin ofuscación.
  • La topología de los Statecharts se almacena como datos en ROM, evitando de esta manera su codificación con código condicional (if-else, switch-case), que se ofusca en la medida que aumenta la complejidad. Adicionalmente, esta estrategia de implementación es sumamente eficiente en términos de tiempo de ejecución.
  • Permite utilizar eventos con y sin parámetros.

Modelo de ejecución

  • Utiliza el modelo de objeto activo como unidad de concurrencia, independientemente de la política de planificación subyacente.
  • La ejecución de las máquinas de estados se realiza bajo el modelo de objeto activo, el cual se constituye por una cola de eventos, un receptor de eventos (generalmente un Statechart) y un hilo de ejecución. Es importante resaltar que el comportamiento de los objetos activos no se limita a las máquinas de estados ya que RKH permite elegir de qué manera se procesan los eventos recibidos. Básicamente esto se debe a que estos son objetos polimórficos.
  • Utiliza el patrón de intercambio de eventos para la comunicación entre objetos activos e ISR.
  • Puede acoplarse a una aplicación funcional existente y trabajar en colaboración. Por lo general, en esta situación, la aplicación basada en RKH resuelve la parte reactiva del sistema.

Pruebas unitarias

  • Provee un entorno para las pruebas unitarias de las máquinas de estados, utilizando los frameworks Unity, Cmock y Ceedling.

Calidad de código

  • Su código fuente está escrito en lenguaje C basado en los principios SOLID, focalizándose en la eficiencia en términos de consumo de recursos, como RAM, ROM y tiempo de ejecución. Su footprint se extiende entre 1K a 6K de ROM.
  • Todos sus módulos poseen el harness de prueba para que estos evolucionen, mediante TDD, en un ambiente controlado y seguro.
  • Su estructura de archivos y directorios es simple e intuitiva.
  • Posee su propio estándar de codificación, el cual puede aplicarse automáticamente a nuevos archivos fuente, mediante la herramienta uncrustify.
  • Provee una serie de plantillas disponibles para comenzar la codificación de nuevos archivos fuente con las secciones y estructuras que utiliza el estándar de codificación de RKH.
  • Gran parte de su funcionalidad puede especializarse, extenderse o bien reemplazarse según necesite la aplicación en cuestión.
  • Permite configurarse en tiempo de compilación, para optimizar recursos.
  • Provee assertion macros, como assert(), allege(), error(), require(), y ensure(), para la gestión de errores, excepciones, precondiciones y postcondiciones, favoreciendo la programación defensiva.

Transportabilidad

  • Compatible con procesadores de 8, 16 y 32bits.
  • A través de una capa de abstracción de plataforma (PAL), puede adaptarse a cualquier procesador, compilador y OS/RTOS.
  • Crear el soporte de una nueva plataforma es un proceso simple, ya que son pocas las dependencias con esta.
  • Puede acoplarse y trabajar en conjunto con cualquier OS/RTOS tradicional, heredando sus capacidades y servicios.
  • En caso de operar sin OS/RTOS, incluye un mecanismo para despachar eventos según la prioridad de los objetos activos (scheduler cooperative non-preemptive).
  • La capa PAL desacopla, de manera independiente, servicios nativos como la cola de eventos, el gestor de memoria dinámica, los temporizadores y el planificador, de forma tal que estos puedan ser provistos externamente, por ejemplo por un OS/RTOS tradicional.
  • Permite adoptar fácilmente mecanismos para el ahorro de energía, en función de la plataforma en uso.
  • Soporta diversas plataformas de uso tradicional en la industria.

Verificación y validación

  • Permite verificar y validar en tiempo de ejecución, el funcionamiento de una aplicación basada en este, mediante su trazador nativo, el cual es flexible, configurable y multiplataforma.

Documentación

  • Está completamente documentado en su manual de referencia, el cual incluye una serie de guías rápidas para su instalación, uso como principiante y avanzado, creación del soporte de nuevas plataformas, como así también la descripción de su estructura interna y la descripción detallada de las aplicaciones demostrativas.

Ejemplos de uso y aplicaciones demostrativas

  • Posee una serie de aplicaciones demostrativas disponibles en diversas plataformas, para utilizarlas como punto de partida en la creación de una nueva aplicación.

Estructura

1- Application

La aplicación específica del sistema, puede constituirse por una parte reactiva y otra no, ambas pueden colaborar entre sí para lograr la funcionalidad del sistema. La parte reactiva utiliza el framework RKH.

2- Reactive part

Se constituye por uno o más Statecharts que se ejecutan en forma simultánea en contexto de sus objetos activos. Estos colaboran entre sí y con su entorno, enviando y recibiendo mensajes asincrónicos.
La aplicación utiliza RKH de manera transparente a la plataforma en uso, mediante la capa de abstracción de plataforma (PAL) y el BSP (Board Support Package). De esta manera, la aplicación se define como cross-platform.
El comportamiento reactivo de un objeto activo puede o no representarse mediante máquinas de estados.

3- Non-reactive part

Parte de la aplicación que no es necesariamente reactiva, por lo general se ejecutan en contexto de hilos del OS/RTOS subyacente y se comunica con la parte reactiva mediante mensajes asincrónicos.

4- Configuration

Define las opciones de configuración del framework RKH independientes de la plataforma subyacente, de acuerdo con las necesidades de la aplicación.

5- Neutral code

Código independiente de la plataforma sobre la cual se ejecuta el framework RKH. Hace uso de las funciones provistas por la plataforma subyacente, a través de la capa PAL, por el BSP, por la aplicación en la implementación de las acciones de los autómatas y las operaciones propias de los objetos activos. Esto último se basa en el principio de Inversión de Dependencias (DIP).

6- Board Support Package (BSP)

Concentra las dependencias de la plataforma que no están estrictamente definidas por el port de RKH. De esta forma, el BSP aumenta la flexibilidad del port en uso, permitiendo que una misma aplicación pueda ejecutarse sobre un mismo port pero en diferentes placas o entornos. Así, las aplicaciones de usuario se convierten en cross-platform. Adicionalmente, RKH define ciertas funciones que requiere proveer el BSP.

7- Platform Abstraction Layer (PAL)

Permite aislar el código de RKH de la plataforma subyacente. La selección de plataforma (port) se realiza en momento de compilación. Específicamente, el archivo rkhplat.h incluye condicionalmente el archivo rkhport.h que corresponda, según la opción de compilación para el port deseado. De igual manera, el archivo rkhtype.h incluye condicionalmente el archivo rkht.h que corresponda, según la misma opción de compilación.
OS/RTOS collaboration
De acuerdo a la configuración provista, la capa PAL desacopla, de manera independiente, los servicios nativos e internos de RKH como Event Queue, Memory Pool y Scheduler, de forma tal que puedan ser provistos externamente, por ejemplo, por un OS/RTOS, sin necesidad de modificar ni el framework RKH ni la aplicación.

8- Port

Concentra las dependencias de la plataforma que requiere RKH. Se constituye básicamente por los archivos rkhport.h, rkhport.c y rkht.h.

9- Plataforma

Se constituye por el procesador, el compilador y el OS/RTOS en caso que exista.

¡Comenzar ahora!

Paso 1

En primer lugar debemos obtener el proyecto del framework RKH.

El cual se constituye por una intuitiva estructura de directorios y archivos, que contienen el código fuente del framework y de las aplicaciones demostrativas, junto con herramientas, documentación y plantillas. El cual podemos descargar o bien realizar una copia de alguno de los repositorios públicos desde Sourceforge o GitHub.
  1. En el primer caso descargamos la última versión del paquete de liberación (o la versión que se desee) desde Sourceforge.
  2. En la segunda alternativa accedemos a uno de los repositorios Git en que se encuentra publicado, Sourceforge o GitHub, desde los cuales podemos:
  3. Descargar una copia de una versión particular del proyecto o
  4. Realizar una copia del repositorio (fork)

Paso 2

Con el proyecto almacenado localmente, recomendamos continuar por alguna de las alternativas propuestas, a partir de las aplicaciones demostrativas que dispone RKH.
  1. Experimentar con alguna de las aplicaciones demostrativas que dispone RKH. Estas son independientes de plataforma y por lo tanto se recomienda comenzar con las plataformas sobre x86 ya sea para Windows o Linux.
  2. Partir de alguna de las aplicaciones demostrativas, modificándola paulatinamente, ejecutando, verificando y validando, hasta lograr la aplicación deseada.

Referencias

[1] L. Francucci, “El paradigma de la programación dirigida por eventos” , August 10, 2016.
[2] Benowitz, “Auto-coding UML Statecharts for Flight Software” , July, 2006.
[3] RKH, “RKH Sourceforge download site,”, http://sourceforge.net/projects/rkh-reactivesys/, August 7, 2010.
[4] Object Management Group, “Unified Modeling Language 2.5,” formal/2015-03-01, 2015.
[5] Herb Sutter, “Prefer Using Active Objects Instead of Naked Threads” , Dr.Dobb’s, June 14, 2010.
[6] Herb Sutter, “Use Threads Correctly = Isolation + Asynchronous Messages” , Dr.Dobb’s, March 16, 2009.
[7] David Cummings, “Managing Cuncurrency in Complex Embedded Systems” , Fujitsu Laboratories Workshop on Cyber-Physical Systems, June 10, 2010.
[8] R. Greg Lavender, Douglas C. Schmidt, “An Object Behavioral Pattern for Concurrent Programming” , 1996.
[9] B. P. Douglass, “Real-Time UML: Advances in the UML for Real-Time Systems (3rd Edition),”, Elseiver, October 4, 2006.
[10] M. Samek, “Practical UML Statecharts in C/C++, Second Edition: Event-Driven Programming for Embedded Systems,” Elsevier, October 1, 2008.
[11] D. Harel, "Statecharts: A Visual Formalism for Complex Systems", Sci. Comput. Programming 8 (1987), pp. 231–274.

Comentarios