IntroducciónGeneralmente, los embedded systems se caracterizan por reaccionar continuamente ante estímulos internos y/o externos. Estas reacciones provocan una acción determinada, la cual está en función del contexto del sistema. Inclusive puede que la misma cambie el estado y modo del mismo. A estos sistemas suele denominárselos Sistemas Reactivos(1). Tradicionalmente el comportamiento reactivo de un sistema, se describe por medio de la combinación de las definiciones de autómatas finitos de Mealy/Moore, representados gráficamente por su correspondiente diagrama de transición de estados(3). Esto permite describir naturalmente su comportamiento en términos de estados, eventos, como así también transiciones. La siguiente figura muestra un diagrama de estados tradicional el cual representa el comportamiento dinámico de un sistema. A α β γ C α B α β Figura 1 Como muestra la figura el diagrama se compone de 3 estados y 6 transiciones. Sin embargo, si el sistema es complejo, dicha representación puede dificultarse, debido al crecimiento exponencial de estados(1), los cuales tienen que permanecer de manera no estratificada o “plana”, resultando en un diagrama caótico y no estructurado. Para que el método estado/evento sea útil, debe ser modular, jerárquico y estructurado. Además, de alguna manera debe resolver el problema del crecimiento exponencial de estados relajando el hecho de que todas las combinaciones de estados tiene que estar representadas explícitamente. Una posible solución al problema anterior es utilizar los conceptos propios del método Statechart(1), el cual constituye un formalismo visual para describir estados y transiciones de manera modular, permitiendo el agrupamiento y refinamiento de estados, entre otras. Resumiendo, Statechart es una extensión de los diagramas de estados convencionales. En Statechart los estados de cualquier nivel se representan con rectángulos, usando la encapsulación para expresar la relación jerárquica. Un simple ejemplo Volviendo a la Figura 1, si ahora utilizamos Statechart para representar el comportamiento del sistema, el diagrama se reduce y clarifica notablemente, como muestra la siguiente figura. 1 D A β α α B γ C Figura 2 Dado que el evento β cambia el estado del sistema a B tanto desde A como C, podemos agrupar estos últimos dentro un nuevo super-estado D y reemplazar las dos flechas de β por una única. La semántica de D es entonces, la XOR entre A y C, es decir, estando en el estado D, el sistema también puede estar tanto en el estado A como el C y no en ambos. Así, D es realmente una abstracción de A y C. El estado D y sus flechas salientes β distinguen una propiedad común de A y C, específicamente, que β dirige al sistema desde estos a B. El hecho de que una transición abandone un super-estado, tal como β en la Figura 2, implica que se abandonen todos sus sub-estados. Esto último es la principal manera en que el método Statechart economiza el número de flechas. Dado que el evento α es capturado en los estados A y C como muestra la Figura 1, y estos pertenecen a D podemos reemplazar estas dos flechas por una única, como muestra la Figura 2, en la cual D captura el evento α. α D β α B Figura 3 D A β α α B C Figura 4 2 A γ C Figura 5 La Figura 2 también podría plantearse desde un ángulo diferente: primero podríamos haber comenzado desde la Figura 3, y luego podría haberse refinado el estado D de forma tal que incluya A y C, como la Figura 4. Sin embargo, habiendo hecho esto, la flecha entrante α no indica a cual de los estados A y C entra. Para especificar esto último, se extiende la flecha α para que apunte directamente a A. Luego, si agregamos la transición γ dentro de D obtendremos la Figura 2. Por lo tanto, el agrupamiento o la abstracción es un concepto bottom-up y el refinamiento es top-down. La pequeña flecha sobre el estado B indica que este es el estado por defecto entre D y B, es decir, indica el estado por defecto del diagrama, mientras que la pequeña flecha en A indica que este es el estado por defecto entre A y C, es decir, indica el estado por defecto del estado D. Las flechas por defecto son análogas a los estados de inicio de los autómatas de estados finito. Por lo tanto, el diagrama de estados debe contener un único estado por defecto, el cual puede ser super-estado o no. Asimismo, cada super-estado, también denominado estado compuesto, debe contener un estado por defecto. Tanto el concepto “zooming-in” como el “zooming-out” pueden aplicarse al ejemplo propuesto. El primero se consigue mirando “dentro” de D y encontrando simplemente la Figura 5, y el último eliminado el interior de D y abstrayendo la Figura 2 hacia la Figura 3. Implementación de Statecharts(1) RKH(6) es una herramienta de desarrollo genérica, flexible, modular, altamente transportable, compatible con ANSI-C y de código abierto, para implementar máquinas de estados jerárquicas y “planas”, basada en los conceptos básicos y modernos de máquinas de estados, propuestos primeramente por David Harel en su trabajo Statechart(1) y luego ampliado por UML Statechart(5). Esta herramienta no implementa la especificación completa ni de UML Statecharts ni de Harel Statechart. Su intención es soportar sólo sus conceptos básicos y suficientes para facilitar el modelado de sistemas reactivos, manteniendo una implementación sólida y eficiente. En términos generales, la implementación de RKH ha sido diseñada desde sus comienzos para utilizarse en plataformas de 8-bits pero puede adaptarse fácilmente a plataformas de 16 e incluso 32-bits. Sus principales características son: • Se basa en tablas de estados. 3 • • • • • • • • • • • • La representación de una máquina de estados es fácil e intuitiva. Refleja el diagrama de estados sin ofuscación. Útil en embedded systems. La mayor parte de la implementación de RKH es independiente de cualquier CPU, OS y compilador. Las aplicaciones que utilizan RKH son altamente mantenibles. Fácil de integrar con cualquier mecanismo de despacho de eventos. La generación de código es flexible y configurable por el usuario. Muy pequeño footprint en RAM/ROM. Soporta estados anidados jerárquicamente (HSM), y máquina de estados “planas”. Soporta pseudo-estados: conditional, junction y shallow/deep history(2). Soporta transiciones compuestas con guardas(2). Documentación completa y manual de referencia detallado. Utilizando RKH A continuación se muestra la representación del diagrama de la Figura 2 utilizando RKH. (1) (2) (3) RKH_CREATE_HSM( example, 0, HCAL, &B, NULL, NULL ); RKH_CREATE_BASIC_STATE( B, 0, NULL, NULL, RKH_ROOT, NULL ); RKH_CREATE_TRANS_TABLE( B ) = { RKH_TRREG( ALPHA, NULL, NULL, &A ), RKH_END_TRANS_TABLE }; RKH_CREATE_COMP_STATE( D, 0, NULL, NULL, RKH_ROOT, &A, NULL ); RKH_CREATE_TRANS_TABLE( D ) = { RKH_TRREG( ALPHA, NULL, NULL, &D ), RKH_TRREG( BETA, NULL, NULL, &B ), RKH_END_TRANS_TABLE }; RKH_CREATE_BASIC_STATE( A, 0, NULL, NULL, &D, NULL ); RKH_CREATE_TRANS_TABLE( A ) = { RKH_TRREG( GAMMA, NULL, NULL, &C ), RKH_END_TRANS_TABLE }; RKH_CREATE_BASIC_STATE( C, 0, NULL, NULL, &D, NULL ); RKH_CREATE_TRANS_TABLE( C ) = { RKH_END_TRANS_TABLE }; (4) (5) (6) (7) (8) (9) (1) Crea la máquina de estados, cuyo nombre es “example”. Indica que su estado inicial es “B”. (2) Crea el estado “B”. Este no tiene dependencia, por lo tanto se lo denomina estado básico. “RKH_ROOT” indica que su padre es la raíz del árbol de estados. (3) Crea la tabla de transición de estados de “B”. (4) Crea el estado “D”. Este tiene dependencia, por lo tanto se lo denomina estado compuesto. Indica que su estado por defecto es “A” 4 (5) Crea la tabla de transición de estados de “D”. (6) (7) (8) (9) Crea Crea Crea Crea el la el la estado “A”. Indica que su estado padre es “D”. tabla de transición de estados de “A”. estado “C”. Indica que su estado padre es “D”. tabla de transición de estados de “C”. Para mayor información consultar el manual de referencia de RKH, el cual se encuentra dentro del paquete de liberación de RKH(6). Debido a la extensión del presente artículo se propone realizar futuras publicaciones en las cuales se detalle: • • Ventajas de los pseudo-estados y guardas en las transiciones. Ejemplos de aplicaciones prácticas en embedded systems utilizando RKH. Descarga http://sourceforge.net/projects/rkh-reactivesys/ Referencias y recursos 1. D. Harel - "Statecharts: A Visual Formalism for Complex Systems". 2. D. Harel – “Semantics of Statecharts”. 3. M. Samek - "Practical UML Statecharts in C/C++, Second Edition: Event4. 5. Driven Programming for Embedded Systems". M. Samek and P. Montgomery - "State-Oriented Programming". M. Samek – “UML Statechart”. Contacto Leandro G. Francucci RKH web site: http://sourceforge.net/projects/rkh-reactivesys/ e-mail:
[email protected] 5