Post on 28-Jul-2015
E S C UE L A T É C N I C A S U PE RI O R D E
I NG E NI E RÍ A D E TE LE C OM UN I C AC I Ó N
U N I V E RSI D AD D E M Á L AG A
P R O Y E C T O F I N D E C A R R E R A
HERRAMIENTAS LIBRES PARA LA IMPLEMENTACIÓN DE SISTEMAS DE CONTROL EN TIEMPO REAL CON
MICROCONTROLADORES ARM7
I N G E N I E R Í A T É C N I C A D E T E L E C O M U N I C A C I Ó N
S I S T E M A S E L E C T R Ó N I C O S
M Á L A G A , 2 0 1 0 A N T O N I O J I M E N E Z B E L L I D O
E S C UE L A T É C N I C A S U PE RI O R D E
I NG E NI E RÍ A D E TE LE C OM UN I C AC I Ó N
U N I V E RSI D AD D E M Á L AG A
Titulación: Ingeniería Técnica de Telecomunicación Sistemas Electrónicos Reunido el tribunal examinador en el día de la fecha, constituido por:
D./Dª. ________________________________________________________
D./Dª. ________________________________________________________
D./Dª. ________________________________________________________
para juzgar el Proyecto Fin de Carrera titulado:
HERRAMIENTAS LIBRES PARA LA IMPLEMENTACIÓN DE SISTEMAS DE CONTROL EN TIEMPO REAL CON
MICROCONTROLADORES ARM7
del alumno/a D. Antonio Jiménez Bellido
dirigido por D. José Manuel Cano García
ACORDÓ POR ______________________________________ OTORGAR LA
CALIFICACIÓN DE _______________________________________________
Y, para que conste, se extiende firmada por los componentes del tribunal, la presente diligencia
Málaga, a ______ de __________________ de _________
El/La Presidente/a El/La Vocal El/La Secretario/a Fdo.: _________________ Fdo.: _________________ Fdo.: _________________
E S C UE L A T É C N I C A S U PE RI O R D E
I NG E NI E RÍ A D E TE LE C OM UN I C AC I Ó N
U N I V E RSI D AD D E M Á L AG A
HERRAMIENTAS LIBRES PARA LA IMPLEMENTACIÓN DE SISTE MAS DE CONTROL EN TIEMPO REAL CON MICROCONTROLADORES AR M7
REALIZADO POR: Antonio Jiménez Bellido
DIRIGIDO POR:
José Manuel Cano García DEPARTAMENTO DE: Tecnología Electrónica TITULACIÓN: Ingeniería Técnica de Telecomunicación Sistemas Electrónicos PALABRAS CLAVE: Microcontroladores, ARM, Sistemas d e control, Hardware in the loop, Sistemas en tiempo real, Free RTOS. RESUMEN:
En este proyecto se estudia el conjunto de herramie ntas libres disponibles para el desarrollo de aplicaciones de c ontrol en tiempo real para la plataforma ARM7. Este estudio incluye un an álisis de la arquitectura ARM7 y el microcontrolador NXP LPC2148 , así como una introducción al sistema operativo FreeRTOS. Adicion almente se realizado la implementación de un autopiloto para un vehículo aéreo no tripulado y se ha validado mediante pruebas tipo hardware in th e loop.
Málaga, Septiembre de 2010
I
CONTENIDO
Contenido .......................................................................................................................... I
Tabla de acrónimos ........................................................................................................ VII
1 Introducción ............................................................................................................. 1
1.1 Estado del arte y tendencias .............................................................................. 2
1.1.1 ARM ............................................................................................................ 2
1.2 Objetivos del proyecto ....................................................................................... 4
1.3 Organización de la memoria .............................................................................. 4
2 Arquitectura ARM7 ................................................................................................... 7
2.1 Introducción ....................................................................................................... 7
2.2 Introducción a ARM7 ......................................................................................... 7
2.3 Características más notables ............................................................................. 8
2.4 El pipeline ........................................................................................................... 8
2.5 Acceso a memoria .............................................................................................. 9
2.6 Registros ........................................................................................................... 10
2.7 Modos de operación y excepciones ................................................................ 11
2.7.1 Interrupciones software ........................................................................... 14
2.8 Conjuntos de instrucciones .............................................................................. 14
2.8.1 Conjunto de instrucciones ARM ............................................................... 15
2.8.2 Instrucciones de salto ............................................................................... 15
2.8.3 Instrucciones de procesado de datos ....................................................... 16
2.8.4 Instrucciones de transferencia de datos .................................................. 17
2.8.5 Operaciones sobre los registros y los bancos de registros ...................... 18
2.8.6 Conjunto de instrucciones THUMB .......................................................... 18
3 Microcontrolador NXP LPC2148 ............................................................................. 21
II
3.1 Introducción ..................................................................................................... 21
3.2 Memoria Flash integrada ................................................................................. 22
3.3 Memoria SRAM integrada ............................................................................... 22
3.4 Mapa de memoria............................................................................................ 22
3.5 Diagrama de bloques ....................................................................................... 24
3.6 Modulo de aceleración de memoria (MAM) ................................................... 25
3.7 Sistema de interrupciones de la familia LPC2000 ............................................ 26
3.8 Gestión de la energía ....................................................................................... 28
3.9 Periféricos de usuario ...................................................................................... 28
3.9.1 E/S de propósito general .......................................................................... 29
3.9.2 TimerS ....................................................................................................... 29
3.9.3 UART ......................................................................................................... 31
3.9.4 Convertidor analógico a digital ................................................................. 32
3.9.5 Convertidor digital a analógico ................................................................. 33
3.9.6 Modulador PWM ...................................................................................... 33
3.9.7 Watchdog timer ........................................................................................ 35
3.10 Hardware de debug ...................................................................................... 36
3.11 Conclusiones................................................................................................. 36
4 Entorno y herramientas de desarrollo ................................................................... 37
4.1 Introducción ..................................................................................................... 37
4.2 El entorno de desarrollo .................................................................................. 38
4.2.1 Ubuntu Linux ............................................................................................ 38
4.3 Herramientas de desarrollo ............................................................................. 38
4.3.1 CodeSourcery G++ Lite ............................................................................. 38
4.3.2 Eclipse IDE ................................................................................................. 39
4.3.3 OpenOCD .................................................................................................. 39
III
4.3.4 Placa de desarrollo Olimex LPC-P2148 ..................................................... 41
4.3.5 Interfaz JTAG Olimex ARM-USB-OCD ....................................................... 42
4.3.6 High IntegRity Staviewer Pluggin .............................................................. 43
4.4 Conclusiones .................................................................................................... 47
5 Sistemas operativos en tiempo real ....................................................................... 49
5.1 Introducción ..................................................................................................... 49
5.2 Multitarea ........................................................................................................ 49
5.3 Multarea y concurrencia .................................................................................. 50
5.4 El planificador .................................................................................................. 50
5.4.1 Aplicaciones de tiempo real ..................................................................... 51
6 Free RTOS ............................................................................................................... 55
6.1 Introducción a FreeRTOS. ................................................................................ 55
6.1.1 Multiprocesamiento en sistemas embebidos pequeños. ........................ 55
6.2 El planificador .................................................................................................. 57
6.2.1 Gestión de procesos ................................................................................. 57
6.2.2 Creación y destrucción de tareas ............................................................. 61
6.3 Gestión del montículo ...................................................................................... 62
6.4 Uso de la pila .................................................................................................... 63
6.5 Mecanismos de comunicación entre procesos (IPC) ....................................... 64
6.6 Rutinas de interrupción. .................................................................................. 65
6.6.1 Abstracción de hardware mediante drivers. ............................................ 67
6.7 Estructura y componentes de un proyecto con FreeRTOS. ............................. 68
6.7.1 Estructura del código fuente de FreeRTOS .............................................. 68
6.7.2 Estructura de un proyecto con FreeRTOS ................................................ 71
6.8 Configuración y optimización. ......................................................................... 73
6.8.1 Macros de traza ........................................................................................ 74
IV
6.9 Conclusiones .................................................................................................... 75
7 Ejemplo de sistema de control en tiempo real: autopiloto para UAV ................... 77
7.1 Introducción ..................................................................................................... 77
7.2 Diseño basado en modelos .............................................................................. 77
7.2.1 Introducción ............................................................................................. 77
7.2.2 Esbozo sobre estabilidad y control de la aeronave .................................. 79
7.2.3 Estabilidad y control longitudinal ............................................................. 79
7.2.4 Estabilidad y control lateral-direccional ................................................... 80
7.2.5 Esbozo del diseño del controlador del viewer ......................................... 81
7.3 Modelado del sistema de control .................................................................... 82
7.3.1 Modelo de la aeronave ............................................................................. 83
7.3.2 Bloque de generación de referencias (Hight Level) ................................. 87
7.3.3 Controlador de bajo nivel ......................................................................... 96
7.4 Verificación del diseño mediante pruebas hardware in the loop (HIL) ........ 103
7.4.1 Metodología empleada .......................................................................... 104
7.5 Implementación del controlador en un microcontrolador NXP LPC2148 con
FreeRTOS .................................................................................................................. 107
7.5.1 Arquitectura software ............................................................................ 107
7.5.2 Implementación de los controladores ................................................... 109
7.5.3 Driver UART ............................................................................................ 116
7.5.4 Comunicaciones con Simulink ................................................................ 117
7.5.5 Configuración de FreeRTOS .................................................................... 118
7.5.6 Estructura del código fuente .................................................................. 119
7.6 Resultados obtenidos .................................................................................... 121
8 CONCLUSIÓN ........................................................................................................ 125
9 Líneas futuras ....................................................................................................... 127
V
Bibliografía .................................................................................................................... 129
Referencias WEB ........................................................................................................... 131
ANEXO A: Familias soportadas por FreeRTOS .............................................................. 133
Anexo B: Código para el cálculo de referencias de trayectorias .................................. 135
VI
VII
TABLA DE ACRÓNIMOS
API: Application programming interface.
ARM: Advanced Risc Machines.
ASIC: Application specific integrated circuit.
ASSP: Application specific standard product.
CAN: Controller area network.
CPU: Central processing unit.
CPSR: Current program status register.
CVS: Concurrent versions system.
DSP: Digital signal proccesor.
FPGA: Field programable gate array.
GCC: GNU compiller collection.
GNU: GNU is Not Unix. Proyecto de software libre.
GPIO: General purpose input/output.
HIL: Hardware in the loop.
I2C: Inter integrated circuit.
I2S: Integrated interchip sound.
IRQ:Interrupt request.
IP: Iternet protocol.
IPC: Inter process comunication
ISR: Interrupt service routine
MCU: Microcontroller unit
MIPS: Million instructions per second.
NED: North, East, Down. Sistema de referencia.
RTOS: Real time operating system.
SIMD: Single instruction multiple data.
VIII
SOC: System in chip.
SPI: Serial port interface.
SPSR: Saved program status register.
UAV: Unmanned aerial vehicle.
USB: Universal serial bus.
VIC: Vectorized interrupt controller.
1
1 INTRODUCCIÓN
Actualmente nos encontramos en un contexto tecnológico en el que la proliferación de
los sistemas embebidos supone uno de los mercados de más rápida expansión. La
exigencia de los consumidores en cuanto a funcionalidad y prestaciones de los
dispositivos electrónicos que usan a diario ha propiciado un gran impulso para el
mercado de los microcontroladores.
Existen en el mercado multitud de arquitecturas y familias que cubren todo el espectro
de aplicaciones, desde pequeños microcontroladores, de coste muy reducido, hasta
SOCs (system on chip) con funciones hasta hace poco reservadas a los ordenadores
personales.
En este contexto, el objetivo del presente trabajo es introducir la arquitectura ARM,
una de las más extendidas en los últimos años y de la que existen variantes para todo
tipo de aplicaciones, desde pequeños sistemas de control y automatización,
procesadores de aplicación, núcleos sintetizables en lógica programable, hasta
procesadores multinúcleo.
Dentro de esta arquitectura nos centraremos en la familia ARM7, que representa el
segmento medio de la arquitectura. Está formado por microcontroladores RISC de 32
bits, con capacidades de cálculo de hasta 130 MIPS, y memorias Flash de hasta 1
Mbyte.
Una de las ventajas de esta familia subyace en el hecho de ser una tecnología
licenciada a múltiples fabricantes, por lo que la oferta de dispositivos disponibles es
muy amplia. Actualmente más de cuarenta compañías1 fabrican implementaciones de
ARM7, disponiéndose de dispositivos con todos los periféricos usados en la industria,
incluyendo controladores Ethernet, CAN, Flexray, SPI, I2C, I2S, USB, y un largo etcétera.
Uno de los objetivos de este proyecto es analizar las capacidades de esta familia para
la implementación de sistemas en tiempo real con unos requisitos computacionales
medios, como suele ser el caso en muchos sistemas de control. Desarrollaremos como
ejemplo la implementación de un sistema de control a partir de un diseño previo
basado en modelos con la herramienta Simulink.
Así mismo, como objetivo adicional, analizaremos las características de la familia
como plataforma para la docencia, estudiando los entornos de desarrollo y
herramientas disponibles, en concreto, configuraremos un entorno de desarrollo
basado en aplicaciones libres y gratuitas en entorno Linux.
1 http://www.arm.com/community/partners/company_list.php
2
1.1 ESTADO DEL ARTE Y TENDENCIAS
1.1.1 ARM
ARM se encuentra entre las empresas líderes de la industria en cuanto a
microprocesadores embebidos de 32 bits, representando el 6% del mercado global de
microcontroladores, y con una amplia implantación en algunos segmentos, como el
85% en smartphones, el 90% en cámaras digitales, el 75% en reproductores
multimedia, 65% en controladores para discos duros y el 30% en TV digitales2.
Hasta la fecha se han fabricado más de 15000 millones de procesadores ARM, de
hecho según ARM Ltd. en la actualidad se fabrican unos diez millones al día.
La siguiente figura recoge las familias de procesadores ARM disponibles actualmente:
Figura 1 Familia de procesadores ARM
En la figura se diferencia tres tipos de procesadores en función de tipo de aplicaciones
a las que van destinadas.
2 ARM anual report 2009: http://media.corporate-ir.net/media_files/IROL/19/197211/ARM_Annual_Report_2009.pdf
3
Los procesadores ARM Cortex-A están principalmente orientados a su integración en
SOC de alto rendimiento, destinados a dispositivos de comunicaciones y multimedia,
como Netbooks, Smartphones, televisiones, routers, telefonía IP etc.
Dentro de esta familia encontramos:
• Cortex-A9: con implementaciones multinúcleo3 entre 800MHz y 2GHz.
• Cortex-A8: procesadores de un solo núcleo hasta 1GHz.
• Cortex-A5: procesadores hasta 800MHz para aplicaciones de bajo coste.
Las series Cortex-M y Cortex-R están destinadas a aplicaciones de tiempo real en las
que se necesitan tiempos de ejecución determinísticos y alto rendimiento.
Especialmente la serie Cortex-R cuenta con instrucciones SIMD en punto flotante y
versiones con hardware redundante para aplicaciones críticas, como por ejemplo los
Texas Instruments TMS570LS con CPU dual sincronizada.
Dentro de la familia Cortex-M encontramos los dispositivos:
• Cortex-M4: orientados sistemas de control y procesado digital de señal para
sistemas de bajo consumo energético.
• Cortex-M3: orientado a aplicaciones en tiempo real, especialmente sistemas de
control y networking.
• Cortex-M1: es un procesador sintetizable destinado a su implementación en
FPGAs.
• Cortex-M0: es un procesador bajo costo y alta eficiencia energética, destinado
a aplicaciones de muy bajo coste.
Los procesadores englobados como Classic ARM Processors incluyen las familias
ARM11, ARM9 y ARM7, y representan las tecnologías más maduras. Son procesadores
de propósito general y alta eficiencia, especialmente indicados para aplicaciones de
bajo coste.
Encontramos los siguientes dispositivos:
• ARM11: procesadores con frecuencias de reloj hasta 1 GHz, de propósito
general. Principalmente empleados a aplicaciones en telefonía móvil, PDAs,
videojuegos.
• ARM9: procesadores de propósito general con extensiones SIMD y DSP. Es la
familia más popular.
3 Hasta cuatro núcleos.
4
• ARM7: microcontroladores de propósito general y bajo coste. Esta familia está
siendo actualmente reemplazada por los nuevos dispositivos Cortex-M3 y
Cortex-M0. Sin embargo presenta un elevado nivel de madurez, y las
implementaciones disponibles son muy robustas, lo que hace que aun sea la
familia de microcontroladores ARM más extendida, representando el 55% de
todos los microcontroladores ARM vendidos en 20094.
1.2 OBJETIVOS DEL PROYECTO
Los objetivos del presente proyecto son:
Estudiar las características de la familia ARM7 y su aplicabilidad en sistemas de control.
Analizar las características y funcionalidad de FreeRTOS como sistema operativo en
tiempo real e implementar como caso práctico el controlador de un autopiloto para un
UAV.
Analizar la viabilidad de la utilización de herramientas libres y gratuitas para la
configuración de un entorno de desarrollo versátil y robusto para microcontroladores
ARM.
1.3 ORGANIZACIÓN DE LA MEMORIA
El presente trabajo presenta de manera progresiva los distintos conceptos que
finalmente permitirán la implementación de un sistema de control en tiempo real con
FreeRTOS en un microcontrolador basado en una CPU ARM7. El contenido de los
capítulos que lo componen es el siguiente:
• En el capítulo dos se introducen las características y arquitectura de la CPU
ARM7.
• En el capítulo tres se estudia el microcontrolador NXP LPC2148, basado en
dicha CPU.
• En el capítulo cuatro se exponen las distintas herramientas y configuración de
un entorno de desarrollo basado en herramientas libres bajo entorno Linux.
• En el capítulo cinco se introducen algunos aspectos básicos de los sistemas en
tiempo real.
4 ARM annual report 2009: http://media.corporate-ir.net/media_files/IROL/19/197211/ARM_Annual_Report_2009.pdf
5
• En el capítulo seis se estudia FreeRTOS como sistema operativo en tiempo real
y se introducen los aspectos fundamentales de su API.
• En el capítulo siete se realiza la implementación con FreeRTOS en una placa de
desarrollo basada en un microcontrolador LPC2148 de un sistema de control
existente. Posteriormente a la implementación, se comparan los resultados
obtenidos mediante simulación en Simulink con los resultados obtenidos en
una simulación tipo hardware in the loop, en la que el algoritmo de control se
ejecuta en el hardware real.
6
7
2 ARQUITECTURA ARM7
2.1 INTRODUCCIÓN
Como se ha comentado anteriormente, poder contar con una plataforma ampliamente
extendida presenta evidentes ventajas en muchos aspectos. Por esa razón se ha
elegido la familia ARM7 como objeto de estudio.
Representa una tecnología madura, con herramientas de desarrollo libres y muy
depuradas, proporcionando a la vez una elevada flexibilidad y rendimiento con unos
costes, tanto de las herramientas como de los dispositivos, muy bajos.
En el desarrollo de este proyecto utilizaremos un microcontrolador NXP LPC2148. Para
poder afrontar un desarrollo con el mismo, estudiaremos los aspectos generales de la
familia ARM7, y posteriormente nos centraremos en las características concretas del
LPC2148.
2.2 INTRODUCCIÓN A ARM7
La familia ARM7 está compuesta por un conjunto de núcleos RISC de 32 bits basados
en las arquitecturas ARMv4T y ARMv5TEJ, optimizados para mantener unos
requerimientos de consumo bajos y coste reducido. La idea clave en la que se basa la
familia es la simplicidad del diseño. El núcleo RISC tiene un conjunto de instrucciones
muy reducido y consecuentemente también un número de puertas bajo, esto permite
un rendimiento alto consumiendo poca área de silicio. Esto lo hace muy adecuado para
sistemas embebidos en los cuales el coste y el consumo energético sean aspectos
fundamentales en el diseño.
La familia está compuesta por varios núcleos, ofreciendo una potencia de
cálculo de hasta 130 MIPS5 :
ARM7TDMI (ARMv4T): es el núcleo más básico. Dispone de una ALU entera y
pipeline de tres etapas.
ARM7TDMI-S (ARMv4T): es una versión sintetizable del ARM7TDMI.
ARM7EJ-S (ARMv5TEJ): es una versión sintetizable mejorada con una unidad de
procesamiento DSP y una unidad de aceleración de ejecución de aplicaciones
Java (ARM Jazelle DBX technology).
5,2 Fuente ARM. www.arm.com
8
ARM720T (ARMv4T): es una versión que incorpora un controlador de memoria
(MMU) y una cache de 8 KB, lo que le permite conectarle una memoria RAM
externa y ejecutar sistemas operativos con requerimientos elevados de
memoria como Windows CE, Linux, Symbian OS, Palm OS.
Actualmente más de cuarenta compañías2 ofrecen microprocesadores,
microcontroladores, SOCs, ASICs, y ASSPs basados en ARM7, y sus aplicaciones cubren
desde cámaras de fotografía digital a sistemas de videojuegos.
En adelante nos centraremos en el estudio del núcleo ARM7TDMI, por ser esta
implementación la más extendida.
2.3 CARACTERÍSTICAS MÁS NOTABLES
Una de las características más notable de la familia ARM es la implementación de dos
conjuntos de instrucciones, uno de 32 bits denominado ARM y otro de 16 bits
denominado THUMB. Este conjunto de instrucciones de 16 bit permite doblar la
densidad de código, y al ser posible cambiar de modo dinámicamente en tiempo de
ejecución, puntualmente podemos operar con el conjunto de instrucciones ARM en
caso de ser necesario.
También es destacable que todas las instrucciones son de ejecución condicionada, esto
es así para tratar de obtener un mejor aprovechamiento del pipeline. Profundizaremos
en esta característica más adelante.
2.4 EL PIPELINE
El ARM7TDMI-S utiliza un pipeline de tres etapas. Este es el tipo de pipeline más simple
posible y no tiene los riesgos de pipelines de más largos, como de lectura antes de
escritura.
Cada una de las etapas del pipeline es ejecutada por un hardware independiente, lo
que permite ejecutar una instrucción mientras se decodifica una segunda y se carga
una tercera, de esta forma la mayor parte de las instrucciones se ejecutan en un único
ciclo de reloj.
9
Modo
ARM
Modo
THUMB
1 2 3 4 5 6
CARGA PC PC -
DECODIFICACIÓN PC-4 PC-2 - -
EJECUCIÓN PC-8 PC-4 - - -
Figura 2 Diagrama de carga del pipeline
• Etapa de carga: la instrucción es cargada de la memoria.
• Etapa de decodificación: la instrucción es decodificada.
• Etapa de ejecución: los registros son leídos del banco de registros. Se
ejecutan las operaciones de la ALU y del registro de desplazamiento y
los registros son escritos con los resultados.
Es importante tener presente que en modo ARM el PC va adelantado ocho bytes
con respecto a la instrucción en ejecución, y en modo THUMB va adelantado
cuatro bytes.
Como es usual, el pipeline es más efectivo con código lineal, ya que en caso de que se
produzca un salto, todo el pipeline es vaciado y es necesario que se vuelva a cargar
completamente antes de recuperar la máxima eficiencia en velocidad de ejecución.
Como veremos más adelante, el conjunto de instrucciones ARM posee algunas
características que nos permitirán optimizar el uso del pipeline para saltos pequeños.
2.5 ACCESO A MEMORIA
El núcleo ARM7TDMI tiene una arquitectura tipo Von Neumann, con un bus de datos
de 32 bits, en la que las direcciones de memoria son lineales y numeradas
ascendentemente desde cero.
El núcleo puede configurarse para trabajar en formatos Big-endian o Little-endian
indistintamente.
Los datos pueden ser:
8 bit (byte)
16 bits (half word)
32 bits (word)
10
La alineación de datos debe ser de 4 bytes para los words, de 2 bytes para half Word, y
de un byte para byte.
2.6 REGISTROS
El ARM7 posee una arquitectura de tipo carga y almacena (load-and-store), por tanto,
cualquier instrucción que procese datos necesita que estos se copien primero en un
conjunto de registros. Tras ejecutarse la operación, los resultados se guardan en
memoria.
El banco de registros de datos lo componen dieciséis registros (R0-R15) de 32 bits, de
los cuales:
• R0-R12 son de propósito general.
• R13 es usado como puntero de pila.
• R14, registro de enlace (Link Register). Cuando se llama a una función, la
dirección de retorno se almacena en este registro. Esto permite la
entrada y salida rápida en funciones que no llamen a ninguna otra
función (“a leaf function”). En otro caso el registro de enlace debe ser
almacenado en la pila.
• R15, es contador de programa.
Curiosamente, algunas instrucciones pueden utilizar los registros R13-R15 como
registros de propósito general.
El registro de estado CPSR (Current Program Status Register) es otro registro de 32bits
que contiene flags que indican es estado de la CPU.
31 30 29 28 27 8 7 6 5 4 3 2 1 0
N Z C V I F T M4 M3 M2 M1 M0
Tabla 1 Registro de estado
Los cuatro bits de más peso son manejados directamente por la CPU e indican las
condiciones de estado de los resultados de las operaciones de procesamiento de
datos.
Los ocho bits de menos peso pueden ser controlados desde la aplicación.
Los flags `F´ e `I´ sirven para habilitar las dos fuentes de interrupción externas a la CPU.
Como veremos en el capítulo siguiente, todos los periféricos del LPC2148 están
conectados a estas dos líneas mediante un controlador de interrupciones vectorizadas.
El flag `T´ sirve para controlar que conjunto de instrucciones se esté ejecutando. Como
se ha comentado anteriormente, el ARM7 es capaz de ejecutar dos conjuntos de
instrucciones, denominados ARM y THUMB y de 32 y 16 bits respectivamente. Más
11
adelante se verá que para cambiar de modo de ejecución, el procedimiento adecuado
no es manipular directamente este bit, si no ejecutar una instrucción de salto con
cambio (BX, BLX) al código THUMB.
Los cuatro bits de menos peso indican el modo de operación de la CPU. En el siguiente
punto veremos los distintos modos en los que puede operar la CPU ARM7.
2.7 MODOS DE OPERACIÓN Y EXCEPCIONES
En este punto veremos los distintos modos de operación de la CPU ARM7 y sus
principales aplicaciones. También introduciremos el manejo de excepciones y su
relación con los modos de operación de la CPU.
Los modos de operación se dividen en dos categorías: privilegiados y no privilegiados.
Los modos privilegiados se utilizan para prestar servicio a interrupciones, excepciones
y para acceder a recursos protegidos. Según el modo de operación tendremos acceso a
un conjunto de registros específico.
En la siguiente tabla se muestran los registros asociados a cada modo de operación:
System & User
FIQ Supervisor Abort IRQ Undefined
R0 R0 R0 R0 R0 R0
R1 R1 R1 R1 R1 R1
R2 R2 R2 R2 R2 R2
R3 R3 R3 R3 R3 R3
R4 R4 R4 R4 R4 R4
R5 R5 R5 R5 R5 R5
R6 R6 R6 R6 R6 R6
R7 R7_fiq R7 R7 R7 R7
R8 R8_fiq R8 R8 R8 R8
R9 R9_fiq R9 R9 R9 R9
R10 R10_fiq R10 R10 R10 R10
R11 R11_fiq R11 R11 R11 R11
R12 R12_fiq R12 R12 R12 R12
R13 R13_fiq R13_svc R13_abt R13_irq R13_und
R14 R14_fiq R14_svc R14_abt R14_irq R14_und
R15(PC) R15(PC) R15(PC) R15(PC) R15(PC) R15(PC)
CPSR CPSR CPSR CPSR CPSR CPSR
SPSR_fic SPSR_svc SPSR_abt SPSR_irq SPSR_und
Tabla 2 Bancos de registros
12
Usualmente, al producirse una excepción es necesario guardar el contexto de
ejecución de la aplicación, formado por el conjunto de registros, para poder
restaurarlo una vez concluido el tratamiento de la excepción. Para facilitar y acelerar
este proceso, en los modos Supervisor, Abort, IRQ y Undefined, los registros R13 y R14
son reemplazados por un nuevo par de registros propios para modo, de esta forma
podemos tener unos punteros de pila y de enlace específicos para este modo. También
tenemos acceso a un registro adicional llamado SPSR (saved program status register),
en el que en el momento de la ocurrencia de la interrupción se copia el contenido del
CPSR, una vez atendida la excepción, al volver al modo usuario el CPSR es restaurado
con los contenidos del SPSR.
El modo FIQ adicionalmente proporciona un conjunto registros propios que sustituyen
a R7-R12, de forma que no es necesario copiar el banco de registros en la pila, lo que
permite reducir el tiempo de repuesta ante una interrupción.
Las funciones de los modos de excepción son las siguientes:
• User (modo usuario): es el único modo no privilegiado. Este modo el estado de
ejecución usual, en el que se ejecutan normalmente las aplicaciones. En este
modo tenemos acceso a los registros R0-R15 y al registro de estado CPSR.
• Supervisor: es un estado protegido, normalmente usado por los sistemas
operativos. La CPU se inicia siempre en este modo después de un reset.
También se puede cambiar a este modo mediante una SWI (interrupción
software).
• System: es un estado protegido, normalmente usado por los sistemas
operativos. A este estado solo se puede acceder desde otro modo privilegiado.
• Interrupt (IRQ): este modo protegido se utiliza para el manejo de
interrupciones. La CPU cambia a este modo ante la ocurrencia de una
interrupción.
• Fast interrupt (FIQ): este modo protegido puede usarse para efectuar una
respuesta rápida ante una interrupción. Veremos su funcionamiento más
adelante. . La CPU cambia a este modo ante la ocurrencia de una interrupción.
Más adelante veremos cómo podemos mapear las fuentes de interrupción a los
vectores FIQ o IRQ.
• Abort mode: la CPU pasa a este modo cuando ocurren un error de datos o de
precarga de instrucción.
• Undefined mode: la CPU pasa a este modo cuando se intenta ejecutar una
instrucción no definida.
Como hemos comentado anteriormente, cuando se produce una excepción, la CPU
cambiará de modo de operación.
13
Las siguientes tablas muestran los vectores asociados a cada modo de operación y el
orden de prioridad de las excepciones.
Excepción Modo Dirección del vector
Reset Supervisor 0x00000000
Instrucción no definida Undefined 0x00000004
Interrupción software (SWI) Supervisor 0x00000008
Aborto de precarga Abort 0x0000000C
Aborto de datos Abort 0x00000010
IRQ(interrupción) IRQ 0x00000018
FIQ(interrupción rápida) FIQ 0x0000001C
Tabla 3 Vectores de interrupción
Prioridad Excepción
1 (La más alta) Reset
2 Data abort
3 FIQ
4 IRQ
5 Prefetch abort
6 (La menor) Undefined instrucción / SWI
Tabla 4 Prioridades de las interrupciones
Ante una excepción ocurre lo siguiente:
-La dirección de la siguiente instrucción a ejecutar (PC +4 en modo ARM) se
guarda en el registro de enlace
-El CPSR se copia al SPSR correspondiente a la excepción producida.
-El PC se carga con la dirección del vector de interrupción correspondiente.
Simultáneamente se cambia de modo, reemplazándose los registros R13 y R14
por los correspondientes.
Al entrar en un modo de excepción el flag ‘I’ del CPSR es activado, deshabilitando así
las interrupciones. Si necesitamos poder atender interrupciones anidadas, debemos
desactivar el flag ‘I’ manualmente para habilitar las interrupciones y meter el
contenido del LR en la pila.
Lo primero que deberá hacer nuestra rutina de tratamiento de interrupción será
guardar el contenido de los registros R0-R12 (R0-R7 en el caso del modo FIQ) para
poder restablecerlos inmediatamente antes de salir de la RTI. La CPU ARM7 facilita
esta tarea mediante las instrucciones STM y LDM, que permiten copiar el banco de
registros completo, o un subconjunto de él a memoria y viceversa mediante una única
instrucción.
14
Una particularidad de la familia ARM es que no existe una instrucción específica para
salir de una interrupción; para salir de la excepción es suficiente con copiar el
contenido del LR al PC mediante una variante específica de la instrucción MOV:
MOVS R15, R14; Mueve el contenido del LR al PC y cambia de modo
En caso de pasar a modo FIQ o IRQ, la instrucción que se esté ejecutando en ese
momento es abortada y descartada, así que en estos casos hay que tener en cuenta
que la dirección almacenada en el LR es la de la instrucción descartada mas cuatro (en
modo ARM), así que al salir de la RTI tendremos que asegurarnos de cargar en el PC la
dirección adecuada (LR-4 en modo ARM). Esto podemos hacerlo con una solo
instrucción variación de la instrucción SUB específica para este propósito:
SUBS R15, R14, #4
En el caso de pasar a modo “data abort”, la excepción ocurrirá una instrucción después
de la ejecución de la instrucción que causo la excepción. En este caso, supuestamente,
nuestra RTI solucionará el problema que causo la interrupción, y al salir lo que
pretendemos es volver a ejecutarla. En este caso tendremos que mover hacia atrás el
PC dos instrucciones.
Adicionalmente al ejecutar MOVS o SUBS la CPU cambiará a modo usuario y restaurará
el contenido del CSPR.
2.7.1 INTERRUPCIONES SOFTWARE
Hay disponible una instrucción capaz de generar una excepción, forzando un cambio a
modo supervisor y provocando un salto al vector de interrupción correspondiente. Al
igual que todas las instrucciones ARM, la ejecución de esta instrucción es condicional.
Los 23 bits de menor peso pueden usarse para almacenar un valor que puede pasarse
como parámetro.
31 28 27 24 23
Condición 1111 Valor
Tabla 5 Parámetro de interrupción software
2.8 CONJUNTOS DE INSTRUCCIONES
Como se ha comentado anteriormente, el ARM7 posee dos conjuntos de instrucciones,
el conjunto ARM, de instrucciones de 32 bits, y el conjunto THUMB, de instrucciones
de 16 bits. Para evitar confusiones, en adelante nos referiremos a la CPU como ARM7,
y al conjunto de instrucciones como ARM.
15
2.8.1 CONJUNTO DE INSTRUCCIONES ARM
Una de las características más interesantes del conjunto de instrucciones ARM es que
todas las instrucciones son ejecutadas condicionalmente dependiendo del resultado
de la anterior. Los cuatro bits de más peso del código de operación son comparados
con los bits de estado del CPSR. Para que la instrucción se ejecute deben coincidir, en
otro caso la instrucción es ejecutada como NOP.
Podemos controlar la ejecución condicional de cualquier instrucción añadiendo los
siguientes prefijos:
Prefijo Flags comparados Significado
EQ Z = 1 Igual
NE Z = 0 Distinto
PL N = 0 Positivo o cero
MI N = 1 Negativo
HI C = 1 y Z = 0 Mayor (sin signo)
CS C = 1 Mayor o Igual (sin signo)
CC C = 0 Menor (sin signo)
LS C = 0 y Z = 1 Menor o Igual (sin signo)
GE N = V Mayor o igual
LT N != V Menor
GT Z = 0 y N = V Mayor
LE Z = 1 y N!=V Menor o igual
VS V = 1 Overflow
VC V = 0 No overflow
AL Todos ignorados Ejecutar siempre
Tabla 6 Prefijos de ejecución condicional
Esta característica permite una implementación muy eficiente de de código con
pequeños saltos.
2.8.2 INSTRUCCIONES DE SALTO
Instrucciones de Salto
B Salto
BL Salto con enlace
BX Salto con cambio
BLX Salto con enlace y cambio
Tabla 7 Instrucciones de salto
La instrucción básica de salto B permite saltos de hasta 32MB. La versión modificada
BL, adicionalmente almacena la dirección de la siguiente instrucción a ejecutar (PC+4)
en el registro de enlace.
16
Las instrucciones BX y BLX además cambian modo de ejecución de AMR a THUMB y
viceversa. Este es el único método que debemos usar para cambiar el modo de
ejecución, nunca tratemos de modificar directamente el flag T del CPSR.
Agregando los prefijos de ejecución condicional podemos codificar saltos condicionales
y llamadas condicionales a funciones en una sola instrucción.
2.8.3 INSTRUCCIONES DE PROCESADO DE DATOS
Instrucciones de procesado de datos
AND AND lógico
EOR XOR lógico
SUB Resta
RSB Resta inversa
ADD Suma
ADC Suma con acarreo
SBC Resta con acarreo
RSC Resta inversa con acarreo
TST Test
TEQ Comprueba igualdad
CMP Comparación
CMN Comparación inversa
ORR OR lógico
MOV Mover
BIC Limpiar bit
MVN Mover inversa
Tabla 8 Instrucciones de procesado de datos
Las instrucciones de procesado de datos permiten, al igual que todas las demás, su
ejecución condicional, además permiten realizar un desplazamiento lógico de hasta 32
bits al segundo operando, todo en un único ciclo.
El formato es el siguiente:
Prefijo de ejecución condicional
Código de operación
Flag para habilitar los códigos de condición
Operandos Desplazamiento
COND OP S R1,R2,R3 xx
Tabla 9 Formato de las instrucciones de procesado de datos
17
Estas características bien aprovechadas (más bien con un buen compilador) permiten
ejecutar muy eficientemente ciertas operaciones, por ejemplo:
if(Z==1)
{
R1 = R2+(R3*8);
}
Adicionalmente la CPU dispone de una unidad MAC (multipy accumulate unit), que
permite la multiplicación de enteros de 16 y 32 bits con acumulación.
Instrucciones de la unidad MAC
MUL Multiplicación, operandos de 16 bit
MULA Multiplicación y acumulación, operandos de 16 bit
UMULL Multiplicación sin signo, operandos de 32 bit
UMLAL Multiplicación y acumulación sin signo, operandos de 32 bit
SMULL Multiplicación con signo, operandos de 32 bit
SMLAL Multiplicación y acumulación con signo, operandos de 32 bit
Tabla 10 Instrucciones de la unidad MAC
2.8.4 INSTRUCCIONES DE TRANSFERENCIA DE DATOS
La CPU ARM7 posee un conjunto de instrucciones para copiar distintos tipos de datos
desde memoria hacia los registros e inversamente desde los registros hacia la
memoria.
Instrucciones de transferencia de datos
LDR Load Word
LDRH Load half Word
LDRSH Load signed half Word
LDRB Load byte
LDRSB Load signed byte
STR Store Word
STRH Store half Word
SRHSH Store signed half Word
STRB Store byte
STRSB Store signed half byte
Tabla 11 Instrucciones de transferencia de datos
18
2.8.5 OPERACIONES SOBRE LOS REGISTROS Y LOS BANCOS DE REGISTROS
El núcleo ARM posee dos instrucciones capaces de cargar o guardar el banco de
registros completo con una sola instrucción.
Carga y almacenamiento del banco de registros
STM Guarda el banco de registro en la memoria a partir de la dirección base indicada
LDM Carga el contenido de la memoria desde la dirección base indicada en el banco de registros.
Tabla 12 Operaciones sobre los bancos de registros
Adicionalmente, la CPU posee una instrucción atómica que permite intercambiar el
valor de dos registros. Esto permite la implementación eficiente de semáforos.
Mediante la operación SWP es posible intercambiar el valor de dos registros de forma
atómica, por lo que está operación está protegida frete a interrupciones.
2.8.5.1 MODIFICACIÓN DEL REGISTRO DE ESTADO (CPSR)
Como se ha indicado en la sección Registros, los registros CPSR y SPSR no forman parte
del banco de registros. Mediante las funciones MSR y MRS podemos copiar el
contenido de estos registros a cualquier registro del banco de registros y viceversa.
Hay que notar que estas funciones no están disponibles en el modo usuario, por lo que
sólo son accesibles desde los modos privilegiados, esto implica que el modo USER no
puede abandonarse salvo a través de la ocurrencia de una excepción.
2.8.6 CONJUNTO DE INSTRUCCIONES THUMB
Tal y como se ha comentado anteriormente, la CPU ARM7 posee un modo de
ejecución alternativo que permite la ejecución de un conjunto de instrucciones de 16
bits. El propósito de este modo de ejecución y este conjunto de instrucciones, es poder
obtener una mayor densidad de código. La utilización del modo THUMB debe ser
analizada por el desarrollador, ya que aunque permite un ahorro de espacio del 30%,
el código en modo ARM es un 40% más rápido, especialmente en algoritmos de cálculo
matemático. Por esta pérdida de rendimiento, en general, la utilización de este modo
no es apropiada para su uso en sistemas de control, por lo que sólo haremos una breve
introducción de sus características más relevantes.
El conjunto de instrucciones THUMB únicamente puede establecerse desde el modo
usuario, modificándose el modo de ejecución a ARM al cambiar la CPU a cualquiera de
los modos privilegiados. El cambio a modo THUMB se efectúa mediante las
19
instrucciones BX o BXL, que efectúan un salto de memoria y un cambio de modo de
ejecución.
Este conjunto de instrucciones THUMB carece de algunas características del conjunto
ARM, como es la ejecución condicional de todas las instrucciones. También se ve
reducido el número de operandos de las instrucciones, que se ve reducido a dos.
Aunque desde este modo tenemos acceso al banco de registros del modo usuario, sólo
podemos operar con los registros R0 a R7, y con algunas instrucciones al resto de
registros. Así mismo, carece de instrucciones para modificar directamente los registros
CPSR y SPSR, por lo que si se necesita modificar explícitamente uno de estos registros,
será necesario cambiar a modo ARM.
20
21
3 MICROCONTROLADOR NXP LPC2148
3.1 INTRODUCCIÓN
Como se comento en la introducción, nos centraremos en el estudio de este
microcontrolador a lo largo del presente trabajo.
En esta sección se mostrarán los datos y características más relevantes del LPC2148,
para más detalles podemos consultar el datasheet del dispositivo.
Las características técnicas de este dispositivo son las siguientes:
• Microcontrolador ARM7TDMI-S.
• Encapsulado LQFP64.
• Entradas y salidas tolerantes a 5V.
• Frecuencia de reloj máxima de 60 MHz
• Oscilador integrado con capacidad de operar desde 1 a 30 MHz
• Diversos modos de bajo consumo, incluyendo habilitación de los relojes de
cada periférico.
• 40 KB de memoria SRAM, 512 KB de memoria flash integrada.
• Macrocélula EmbeddedICE RT y Embedded Trace para depuración en tiempo
real integrada.
• Controlador USB 2.0 Full Speed con 2kB de memoria SRAM dedicada y 8 KB
adicionales accesible mediante DMA.
• Dos conversares A/D de 10 bits, multiplexados desde 14 entradas analógicas.
• Un conversor D/A.
• Dos timers con cuatro módulos de captura y otros cuatro de comparación cada
uno.
• Reloj de tiempo real con oscilador dedicado.
• Dos UARTS tipo 16C550
• Dos controladores I2C de 400 kbits/s
• Controlador SPI
• Controlador SSP
• Controlador de interrupciones vectorizadas.
• Nueve entradas de interrupción externas.
Las aplicaciones típicas de este microcontrolador son:
• Control industrial
• Gateway de comunicaciones
• Sistemas de control de accesos
• Sistemas médicos.
• Sistemas de propósito general
22
3.2 MEMORIA FLASH INTEGRADA
El LPC2148 integra 512 KB de memoria Flash. Esta memoria puede ser usada
indistintamente para almacenamiento de código y datos.
La memoria puede escribirse mediante el la interfaz JTAG integrada o a través de la
UART0 mediante la funcionalidad In System Programing, o desde una aplicación en
ejecución, por ejemplo, un boot loader.
Esta memoria proporciona un mínimo de cien mil ciclos de borrado/escritura, y un
retención de datos de veinte años.
3.3 MEMORIA SRAM INTEGRADA
El LPC2148 proporciona 32 KB de SRAM, que puede ser accedida como datos de 8, 16
y 32 bits.
La memoria está diseñada para ser accedida como memoria direccionada en bytes. Los
accesos a datos de media palabra y una palabra se hacen a las direcciones alineadas,
en concreto, para las medias palabras se ignora el bit 0 de la dirección, y para palabras
completas se ignoran los bits 0 y 1.
3.4 MAPA DE MEMORIA
Independiente del número de buses presentes en el LPC2148, este microcontrolador
posee un mapa de memoria completamente lineal, tal y como se puede apreciar en la
siguiente figura:
23
Figura 3 Mapa de memoria del LPC 2148
Como se puede observar, la memoria Flash integrada se encuentra ubicada a partir de
la dirección 0x00000000, y la memoria SRAM se encuentra ubicada a partir de la
dirección 0x40000000.
El microcontrolador cuenta con un software de depuración (ARM real monitor) y otro
carga (Flash boot loader), preprogramados de fábrica en el rango 0x7FFFFFFF a
0x80000000.
Los periféricos conectados al bus VPB están mapeados en el intervalo de direcciones
0xE0000000 a 0xE0200000. Dentro de este rango, para cada periférico se reserva un
espacio de 16K.
La unidad de control de interrupciones vectorizadas se encuentra a partir de la
dirección 0xFFFFF000.
Adicionalmente, la región comprendida entre 0x8000000 y 0xE000000 está reservada
en todos los dispositivos de la familia LPC2xxx para memoria externa. Aunque el
24
LPC2148 no cuenta con un bus de memoria externa, otros dispositivos de la familia,
como los LPC22xx, si cuentan con dicho bus.
3.5 DIAGRAMA DE BLOQUES
Aunque para el programador, todos los periféricos están en un rango continuo de 32
bits, internamente el dispositivo está compuesto por un conjunto de buses, tal como
puede apreciarse en el siguiente diagrama de bloques del dispositivo.
Figura 4 Diagrama de bloques del LPC2148
25
El núcleo ARM7 está conectado al bus AHB6. A este bus está conectado el controlador
de interrupciones y un puente al bus VPB7.
El resto de periféricos está conectado directamente al bus VPB. Este bus VPB posee un
divisor de reloj de forma que puede funciona a una velocidad inferior a la del núcleo,
esto permite por un lado establecer mecanismos de ahorro de energía, y por otro,
poder conectar periféricos lentos sin que suponga un cuello de botella para el bus
AHB.
Para conectar la CPU a la memoria Flash y SRAM existe un tercer bus dedicado.
3.6 MODULO DE ACELERACIÓN DE MEMORIA (MAM)
Este módulo es fundamental para conseguir una elevada velocidad de ejecución, ya
que la memoria Flash es más lenta que la CPU, con un tiempo de acceso de 50ns, lo
que limitaría la velocidad de ejecución a 20MHz.
Para acelerar la ejecución, la memoria Flash está dividida en dos bancos con una
anchura palabra de 128 bits cada uno, accesibles de forma independiente, esto
permite cargar cuatro instrucciones ARM u ocho instrucciones THUMB en una sola
operación.
Estos bancos están entrelazados de forma que mientras se ejecuta el código cargado
desde un banco, se efectúa la carga del siguiente. Este método funciona muy bien con
las instrucciones ARM, que permiten suavizar pequeños saltos mediante los códigos de
condición vistos en el capítulo anterior. Adicionalmente, el módulo MAM cuenta con
buffers para los saltos y bucles, de forma que no tengan que efectuarse operaciones
de carga para instrucciones ejecutadas recientemente.
El módulo MAM se programa mediante dos registros: el registro de temporización
(timing register), y el registro de control (control register).
Mediante el registro de temporización podemos establecer la relación entre el reloj de
la CPU y el tiempo de acceso a flash, en el podemos fijar el números de ciclos de reloj
necesarios para acceder a la Flash. Como nuestra CPU trabaja a 60 MHz, y la frecuencia
máxima de acceso a la Flash es de 20Mhz, el numero de ciclos de reloj requeridos será
de tres, de forma que por cada tres ciclos de reloj podemos cargar cuatro
instrucciones, con lo que el MAM siempre tendrá instrucciones disponibles para la
ejecución.
6 Advanced High performance Bus, definido por ARM.
7 VLSI Peripheral Bus.
26
El registro de configuración del MAM sirve para establecer el modo de operación del
módulo. Hay tres modos posibles:
Figura 5 Modos de operación del MAM
Después de un reset, el MAM está deshabilitado, y todos los accesos serán directos a
Flash.
También es posible habilitar solo parcialmente el MAM, pero haciendo que los saltos y
los accesos a datos en Flash se hagan directamente.
Finalmente, podemos habilitar completamente el MAM, de forma que todos los
accesos a Flash se hagan a través del MAM.
La razón de estos es poder permitir un modo de ejecución perfectamente
determinista, ya que el uso del MAM implica tiempos de ejecución no determinísticos.
En cualquier caso, es posible mediante herramientas de depuración, determinar el
tiempo de ejecución del código. El MAM cuenta con una serie de registros que recogen
estadísticas sobre los accesos a Flash y a los búferes del MAM. Estas medidas nos
proporcionan información sobre la eficacia del MAM en nuestra aplicación.
En este punto, es importante observar que sí es posible obtener una ejecución
determinística a la máxima velocidad de CPU si cargamos el código de programa en
memoria SRAM, con el inconveniente de que la cantidad de esta es más limitada que
de Flash.
3.7 SISTEMA DE INTERRUPCIONES DE LA FAMILIA LPC2000
En este punto trataremos el hardware implicado en el manejo de interrupciones
externas a la CPU ARM7, englobando tanto los periféricos integrados en el LPC2148
como las fuentes de interrupción externas.
La CPU ARM7 posee dos líneas para interrupciones externas, una para interrupciones
rápidas (FIQ), y otra para interrupciones generales (IRQ). Para poder conectar
múltiples periféricos a estas dos únicas líneas, el LPC2148 (y toda la familia LPC2000)
integra un modulo controlador de interrupciones vectorial (VIC).
27
Figura 6 Controlador de interrupciones
El VIC permite conectar todas las fuentes de interrupción a la CPU de tres formas:
como interrupción FIQ, como interrupción IRQ vectorizada, y como interrupción IRQ
no vectorizada.
Como se ha comentado, cualquier fuente de interrupción puede asignarse como FIQ,
aunque hay que tener en cuenta que es conveniente no tener más de una interrupción
de este tipo, ya que en ese caso tendríamos que inspeccionar cual es la fuente de la
interrupción, lo que aumentaría el tiempo de atención a la misma. Ante la ocurrencia
de una interrupción FIQ, el procesador cambiará a modo FIQ y saltará al vector FIQ.
A diferencia que las interrupciones FIQ, las interrupciones IRQ pueden vectorizarse. El
VIC tiene una tabla con 16 slots para los vectores, cada slot se compone de un registro
de dirección y un registro de control, mediante el cual podemos asignar el vector a una
fuente de interrupción.
Cuando se genere una interrupción, el VIC cargara la dirección correspondiente a esa
fuente de interrupción en el registro de vector de dirección (Vector Address Register),
simultáneamente la CPU pasará a modo IRQ y saltará al vector de interrupción IRQ, en
el cual se deberá cargar el valor del VIC en el PC para entrar en el código de
tratamiento de interrupción correspondiente.
Como hemos comentado anteriormente, el VIC es capaz de gestionar hasta 16 fuentes
de interrupción como interrupciones vectorizadas y al menos una como interrupción
FIQ. Si tuviésemos más de 17 fuentes de interrupción, podríamos tratar el resto como
interrupciones no vectorizadas. En este caso se saltará a un vector de interrupción por
defecto en el que se deberá comprobar cuál es la fuente de interrupción y ejecutar el
código adecuado.
28
3.8 GESTIÓN DE LA ENERGÍA
El LPC2148 provee varios mecanismos de ahorro energético. Mediante un uso
adecuado del divisor del VPB podemos reducir el consumo de energía global del
microcontrolador. Adicionalmente, el LPC2148 posee algunas características de ahorro
energético adicionales.
La CPU ARM7 tiene dos modos de apagado que pueden controlarse desde el registro
PCON. Así, podemos detener la CPU completamente pero dejar los periféricos
funcionando normalmente, de forma que cuando se produzca una interrupción la CPU
se active.
El otro modo de apagado detiene tanto la CPU como los periféricos. En este modo la
ejecución solo podrá ser reanudada mediante una fuente de interrupción externa.
Adicionalmente es posible controlar cada periférico integrado individualmente, de
forma que solo estén en funcionamiento los necesarios para la aplicación.
Hay que tener en cuenta que no es posible depurar el dispositivo cuando entra en
algún modo de ahorro de energía.
3.9 PERIFÉRICOS DE USUARIO
En las próximas secciones comentaremos los periféricos de usuario de uso más común
presentes en el LPC2148.
Como se ha comentado anteriormente, el objeto de este documento no es sustituir al
manual de usuario del LPC2148, por lo que solo se introducirán los aspectos
fundamentales de algunos de los periféricos del microcontrolador.
Antes de abordar los distintos periféricos, hay que tener muy en cuenta que en el
LPC2148 todos los pines de E/S pueden estar conectados internamente mediante un
bloque multiplexor a varios periféricos. Este bloque multiplexor, llamado pin select
block permite configurar un pin del dispositivo como GPIO o rutearlo a uno de otros
tres periféricos, por lo que puede darse la situación de que no puedan usarse dos
periféricos simultáneamente. Esta configuración se hace mediante los registros
PINSELn.
29
Figura 7 Pin select block
3.9.1 E/S DE PROPÓSITO GENERAL
Después de un reset, el pin connect block configura todos los pines del LPC2148 como
entradas de propósito general (GPIO).
Podemos acceder a los puerto de E/S de propósito general del LPC2148 a través de un
conjunto de registros conectados directamente al bus local de la CPU, por lo que es
posible manipularlos a la velocidad de la CPU. Es posible controlar la dirección de cada
bit de los puertos.
La lectura de los puertos, independientemente del estado, se hace a través de los
registros IOPIN.
La escritura se hace a través de los registros IOSET y IOCLR, y la configuración como
entrada o salida se hace en los registros IODIR.
3.9.2 TIMERS
El LPC2148 incluye dos timers de 32 bit. Estos timers son idénticos, y pueden funcionar
como timers o como con contadores. Cada timer cuenta ciclos del reloj PCLK del bus
VLSI (funcionando como timer) o de un reloj externo (funcionando como contador)
tras dividirlo mediante un divisor programable de 32 bits (PC, prescale counter).
30
Figura 8 Diagrama de bloques de los timers.
El valor del PC se incrementará con cada ciclo de PCLK hasta alcanzar el valor
almacenado en el registro de pre escalado PR, en ese momento el valor del contador
se incrementará y el PC se reseteará a cero.
Cada timer cuenta con cuatro registros de captura (CR), en los cuales podemos
almacenar al valor del timer ante la ocurrencia de una transición en una señal de
entrada externa. Esto puede ser útil por ejemplo para demodular señales PWM, medir
frecuencias, etc.
Cada uno de estos registros de captura tiene un pin de entrada asociado que puede
habilitarse mediante el pin connect block, y puede configurarse mediante el registro
TnCCR para ser sensible a flancos de subida y/o de bajada y opcionalmente generar
una interrupción.
31
Cada timer también cuenta con cuatro registros de comparación (MR), mediante los
cuales podemos disparar acciones, como generar una interrupción (configurable en el
registro TnMCR) o modificar un pin de salida (configurable en el registro TnEMR).
3.9.3 UART
El LPC2148 integra dos UARTs conformes con el estándar 550, tanto en
funcionamiento como en el orden de los registros. Estas dos UARTs son idénticas, salvo
que la UART1 posee líneas adicionales para control de MODEMs.
La siguiente figura muestra el diagrama de bloques de la UART1 y su conexión al bus
VPB. La UART0 es exactamente igual, salvo por que no incluye el bloque etiquetado
como MODEM:
Figura 9 Diagrama de bloques de la UART 1
La UART incluye un buffer de recepción y de transmisión de 16 bytes, siendo el de
recepción configurable para producir interrupciones tras la recepción de 1, 4, 8 y 14
32
bytes. Como en el resto de periféricos, para la utilización de las UARTs será necesario
configurar correctamente el pin connect block.
Los parámetros de transmisión de las UARTs se configuran en registro LCR (line control
register).
El baud rate generator de las UARTs consiste en un divisor de 16 bits conectado al reloj
de periféricos (PCLK). Tendremos que configurar este divisor para obtener una
frecuencia 16 veces superior a la que queramos tener en la línea de transmisión. El
valor de este divisor se almacena en dos registros de 8 bits, DLM (divisor latch MSB) y
DLL (divisor latch LSB).
La operación de las FIFOs es transparente para el programador. Una vez configurado su
tamaño, la escritura en el THR (transmit holding register) o la lectura en el RBR (receive
buffer register), insertaran o extraerán un byte en la FIFO.
Aunque las UARTs poseen un canal dedicado en el VIC, éstas a su vez pueden generar
tres tipos de interrupción diferentes, por lo que en la RTI habrá que determinar la
causa de la interrupción. Estas causas pueden ser, un error en la transmisión, que
puede ser de diversos tipos, la transmisión de todos los bytes de la FIFO de
transmisión, o la recepción de un número de bytes configurable.
3.9.4 CONVERTIDOR ANALÓGICO A DIGITAL
El LPC2148 integra un convertidor A/D de 10 bits de aproximaciones sucesivas con
ocho entradas analógicas multiplexadas. Como en el resto de periféricos, el reloj del
convertidor deriva de PCLK, teniendo en cuenta las restricciones temporales del
convertidor, tendremos que configurar el registro CLKDIV de forma que la frecuencia
del reloj del convertidor no sea mayor que 4.5MHz.
Podemos seleccionar la resolución de la conversión entre 3 y 10 bits, modificándose
por tanto el tiempo de conversión.
El convertidor puede operar en dos modos: un modo individual, en el que se realiza
una conversión sobre el canal seleccionado, y un modo ráfaga, en la que se realizan
conversiones sobre todos los canales configurados. En ambos casos, al terminar el
proceso puede generarse una interrupción. También puede configurarse para que las
conversiones se realicen de forma continua, sin necesidad de iniciar el proceso tras
cada interrupción, pudiendo conseguirse de este modo alcanzar la máxima tasa de
conversión.
33
3.9.5 CONVERTIDOR DIGITAL A ANALÓGICO
El convertidor digital analógico es el periférico más sencillo del LPC2148, ya que consta
de un único registro (DACR) en el que podemos escribir directamente el valor a
convertir.
Este conversor es de 10 bits y como los otros periféricos es necesario configurar el
registro PINSELn correspondiente para conectarlo a su pin de salida asociado.
Como única particularidad, este conversor puede operar en dos modos: un de bajo fan
out (350 µA) y alta velocidad de conversión (1µs), y otro de alto fan out (700 µA) pero
más lento (2.5 µs). Este modo se configura con el bit 15 del registro DACR.
3.9.6 MODULADOR PWM
El modulador PWM del LPC2148 es similar a los timers de propósito general, con
hardware adicional que le permite generar seis señales PWM con modulación de un
flanco o tres de dos flancos, de hecho el modulo PWM puede utilizarse como un timer
adicional si no se habilita el modo PWM.
La principal diferencia en cuanto al comportamiento, con respecto a los timers de
propósito general funcionando como contadores, es que en los timers, cuando se
escribe un valor nuevo en el registro de comparación, este valor se hace efectivo
inmediatamente y además eso ocurre para cada registro de comparación, lo que
puede provocar glitches y una desincronización de las señales PWM entre los distintos
canales. Para evitar esto, el modulador PWM implementa un mecanismo de registros
sombra que permite que todos los valores se actualicen simultáneamente y al
comienzo de un nuevo ciclo, con lo que puede generarse la señal PWM de forma
correcta.
Este periférico cuenta con siete registros de comparación, cada uno de los cuales está
conectado a una salida. Puede programarse para poner la salida a uno, cero o no hacer
nada cuando se alcance el valor del registro de comparación.
Como puede apreciarse en la figura, las salidas de estos registros de comparación
están conectadas a registros S/R, en los cuales la entrada S es seleccionable entre la
salida match del registro de comparación 0 y la salida del registro de comparación en
cuestión. De este modo se puede implementar la modulación de dos flancos o de un
solo flanco.
34
Figura 10 Diagrama de bloques del módulo PWM
En el caso de modular solo un flanco, con el registro de comparación 0 podemos
controlar el periodo total del ciclo, y con el resto de registros de comparación,
controlamos el ciclo de trabajo. En este modo la señal Match0 está conectada a la
entrada S de todos los biestables, con lo que al final de cada ciclo se pondrán a 1.
Para la modulación de dos flancos, el registro de comparación 0 solo se utiliza para
controlar el periodo de la señal. En este caso las señales conectadas a los biestables
son las correspondientes a los registros de comparación 1 a 6, de forma que podemos
controlar la conmutación de los flancos de bajado y de subida.
35
3.9.7 WATCHDOG TIMER
Es común en los microcontroladores contar con un mecanismo de seguridad que
permita al sistema autoresetearse ante un fallo. Este mecanismo es habitualmente, y
en el LPC2148, usar un timer que provocará un reset global en caso de
desbordamiento, por lo que en nuestro software insertaremos una rutina de resetéo
que se ejecutara periódicamente.
El watchdog timer (WDT) se controla a través de cuatro registros. El timeout se
programa en el registro WDTC. La siguiente figura muestra su diagrama de bloques:
Figura 11 Diagrama de bloques del WDT
El watchdog puede configurarse mediante el registro WDMOD para generar una
interrupción o bien un reset. En caso de generar un reset, activará un flag indicando
que se ha producido un timeout, de forma que después del reset, el programa puede
determinar si se está iniciando después de un reset debido a un fallo.
36
Tanto para iniciar el watchdog como para resetearlo periódicamente, tenemos que
realizar una secuencia de inicio, consistente en escribir consecutivamente 0xAA y 0x55
en el registro WDFEED.
En cualquier momento podemos leer el valor de la cuenta del watchdog timer en el
registro WDTV.
3.10 HARDWARE DE DEBUG
El LPC2148 incluye varios mecanismos hardware para permitir la depuración en
circuito. El chip incluye un puerto JTAG, mediante el cual podemos efectuar una
depuración básica, controlando la ejecución, insertando breakpoints e inspeccionado
la memoria, y un macrocélula ARM embedded trace module, que permite una
depuración más avanzada, que permite trazar código en tiempo real, hacer análisis de
cobertura de código y de rendimiento, pero que requieren hardware adicional a la
interfaz JTAG, y que por tanto no cubriremos en el presente trabajo.
3.11 CONCLUSIONES
Como hemos visto a lo largo del presente capítulo, el LPC2148 tiene unas
características adecuadas para su uso como microcontrolador de propósito general, así
como suficiente capacidad de cálculo y de E/S como para poder utilizarse en sistemas
de control.
También es muy interesante la integración del puerto JTAG para depuración, ya que
otras familias, la depuración en circuito solo puede llevarse a cabo con costosos
emuladores adicionales.
37
4 ENTORNO Y HERRAMIENTAS DE DESARROLLO
4.1 INTRODUCCIÓN
A la hora de elegir una plataforma hardware para realizar un desarrollo,
independientemente de la capacidad computacional y de E/S de la misma, es muy
importante tener en cuenta otras consideraciones que pueden afectar sensiblemente
al proceso de desarrollo con dicha plataforma. Uno de los elementos más importante a
considerar son el entorno y las herramientas de desarrollo disponibles.
A la hora de elegir una herramienta de desarrollo, podemos tener en cuenta los
siguientes requisitos:
• Adecuación al proceso de desarrollo que vamos a aplicar:
o Debemos elegir una herramienta coherente con el proceso de
desarrollo que queramos seguir. Existen multitud de herramientas,
basadas en lenguajes de programación convencionales, programación
gráfica, diseño basado en modelos, etc.
• Capacidad de depuración y traza de código:
o Si bien en cualquier entorno la capacidad de depuración y traza de
código es una funcionalidad obligada, en los sistemas en tiempo real
cobra un valor especial, ya que posiblemente necesitemos calcular
tiempos de ejecución y monitorizar el uso de la CPU de forma precisa.
• Disponibilidad de hardware para depuración:
o Relacionado con el punto anterior, es interesante poder contar con una
variada oferta de herramientas hardware para depuración compatibles
con el entorno de desarrollo, de manera que no dependamos de un solo
fabricante.
• Existencia de una amplia base de usuarios:
o Es quizás unos de los puntos más importantes, ya que las plataformas
con muchos usuarios suelen estar muy documentadas no solo por los
fabricantes, si no por las comunidades de usuarios, existiendo foros en
los que se intercambia conocimiento técnico y se puede obtener ayuda
de forma gratuita. También es interesante ya que las plataformas
ampliamente extendidas suelen estar más depuradas y optimizadas
simplemente por el hecho de que son utilizadas por un gran número de
usuarios, lo que implica que es utilizada en multitud escenarios
distintos.
• Coste de las herramientas:
o Más que un requisito es una limitación. Con toda seguridad, a la hora de
elegir el entorno de desarrollo tendremos una limitación
38
presupuestaria. Como veremos más adelante, y como suele ocurrir en
otros ámbitos, no siempre la mejor herramienta es la más cara.
Existen números compiladores y entornos de desarrollo tanto libres como propietarios
para microcontroladores y microprocesadores ARM. En el presente trabajo, se ha
optado por usar únicamente herramientas libres disponibles de forma gratuita y con
licencia GNU GPL u otras similares.
Para facilitar la redistribución del entorno de desarrollo, se empleara un sistema
operativo virtualizado, de forma que no sea necesario hacer ningún tipo de
configuración al instalar el entorno de trabajo en una máquina nueva, a la vez que se
hace completamente portable.
Como sistema operativo virtualizado se ha utilizado la distribución de Linux Ubuntu
10.4 LTS (Long Term Support), que una versión con soporte a largo plazo (tres años).
Como se ha comentado anteriormente, el entorno completo de desarrollo se facilita
como una imagen de máquina virtual para VMWare, de forma que no haya que
realizar el largo proceso de instalación y configuración en las máquinas de desarrollo.
En cualquier caso, en los siguientes punto explicaremos es proceso de instalación de
todas las herramientas necesarias.
4.2 EL ENTORNO DE DESARROLLO
4.2.1 UBUNTU LINUX
Como sistema operativo se ha optado por la distribución Ubuntu de Linux, debido a su
probada solidez y amplia implantación entre los usuarios.
Se ha elegido una versión LTS para asegurar la operatividad del entorno a medio plazo.
La instalación de Ubuntu es un proceso sencillo, en el que nos limitaremos a seguir el
asistente de instalación.
4.3 HERRAMIENTAS DE DESARROLLO
4.3.1 CODESOURCERY G++ LITE
Codesourcery G++ Lite es una distribución libre del toolchain GNU. Es ofrecido por la
compañía Codesourcery, que además comercializa versiones de pago que integran un
IDE basado en Eclipse, muy similar al que instalaremos nosotros posteriormente, y
opciones de soporte.
39
Está disponible para varias familias de procesadores, obviamente nosotros
instalaremos la versión para ARM.
La versión Lite solo incluye las GCC:8 los compiladores de C y C++, ensamblador, linker,
las librerías estándar y debugger.
La elección de usar las GCC se debe básicamente al hecho de que las herramientas son
gratuitas y de que disponen de un amplio soporte.
El rendimiento de estas herramientas es muy bueno, comparable a cualquier
herramienta propietaria, obteniéndose resultados en cuanto tamaño del código
generado y velocidad de ejecución muy parecidos. Existen múltiples comparativas de
rendimiento en la red, siendo una de las más completas la realizada por Raisonance9.
Por otra parte, el depurador GDB se integra bien en nuestro entorno de desarrollo,
permitiéndonos depurar código en el microcontrolador usándolo de forma conjunta
con OpenOCD y una interfaz JTAG, tal y como veremos más adelante.
4.3.2 ECLIPSE IDE
Eclipse es un popular entorno de desarrollo (IDE) gratuito y de fuentes abiertas.
Aunque inicialmente el fue un proyecto iniciado por IBM, en la actualidad es
desarrollado y soportado por la Eclipse Foundation, que es una fundación sin ánimo de
lucro financiada por sus miembros estratégicos, entre los que se encuentra compañías
como IBM, NOKIA, SAP, ORACLE, CISCO, Motorola o BlackBerry.
Este IDE es neutral, extensible a múltiples lenguajes de programación y herramientas
(compiladores, debuggers, etc.).
En este proyecto usaremos la versión Eclipse CDT10. Esta versión proporciona un
entorno de desarrollo para C y C++, que integraremos con nuestro compilador.
4.3.3 OPENOCD
OpenOCD es una utilidad software que permite interfasear el depurador GPB con la
interfaz JTAG para poder programar y depurar el microcontrolador. GDB establece una
8 GNU Compiler Collection
9 http://www.raisonance.com/arm_benchmark.html
10 C/C++ Development Tooling
40
conexión TCP/IP con OpenOCD, y éste, en base a una serie de archivos de
configuración, se comunicara con la interfaz JTAG que controlará el estado de
ejecución del microcontrolador a través del TAP (Test Access Port) del mismo.
Esta herramienta es muy flexible, ya que incluye un intérprete de lenguaje Tcl, lo que
le permite ejecutar scripts muy complejos. En el caso del LPC2148 como en otras
muchas plataformas, no tendremos que escribir los scripts de configuración, ya que
con la distribución de la herramienta se incluyen diversos scripts para multitud de
plataformas, que además nos pueden servir como punto de partida para crear scripts
más personalizados, como haremos más adelante. Estos scripts se encuentran en el
directorio scripts (normalmente en /usr/share/openocd/scripts).
Hay tres tipos de scripts, contenidos en sus correspondientes subcarpetas:
• Interface: para cada tipo de adaptador JTAG soportado
• Board: para distintas placas de desarrollo
• Target: específicos para cada CPU
Normalmente solo tendremos que hacer referencia a dos scripts, el de configuración
de interfaz y el de la placa que estemos utilizando.
En el contexto de este proyecto configuraremos la ejecución OpenOCD desde eclipse
como herramienta externa, para lo cual definiremos dos configuraciones de ejecución
en el menú “External tools configuration”.
La primera configuración será para la utilización de OpenOCD para depuración. La
siguiente captura de pantalla refleja la configuración necesaria:
Figura 12 Configuración de OpenOCD
41
Se puede observar que ejecutamos los scripts de configuración de la interfaz JTAG y
del microcontrolador.
Para iniciar una sesión de depuración tendremos siempre que ejecutar esta
configuración desde Eclipse.
Adicionalmente, necesitaremos configurar la depuración en eclipse. Para ello
añadiremos una configuración de depuración de tipo “Zylin embedded debug”.
Tendremos que establecer como debugger arm-none-eabi-gdb, y configurar los
comandos de inicialización de tal y como están definido en cualquiera de los proyectos
de ejemplo incluidos en el DVD adjunto.
La segunda configuración es específica para flashear el microcontrolador:
Figura 13 Flasheo del micro con OpenOCD
En esta configuración además ejecutamos un script específico para flashear el micro.
Cuando generemos una nueva versión de un programa, debemos cargarla en la flash
del microcontrolador usando este script. Este script se adjunta en el DVD que
acompaña al presente documento.
4.3.4 PLACA DE DESARROLLO OLIMEX LPC-P2148
Para el desarrollo del sistema de control emplearemos esta placa de desarrollo, basada
en un microcontrolador LPC2148.
42
Figura 14 Olimex LPC-P2148
Esta placa proporciona un puerto JTAG para depuración, así como el hardware
adaptador de nivel para dos puertos RS232 y USB.
También incluye un socket para tarjetas SD, botón de reset, dos botones de usuario,
un buzzer, dos LEDs y un potenciómetro conectado a un canal del conversor A/D.
Esta placa incorpora un rectificador de tensión, por lo que puede alimentarse a 6V DC.
También puede alimentarse a través del puerto USB.
4.3.5 INTERFAZ JTAG OLIMEX ARM-USB-OCD
Para depurar y programar el microcontrolador LPC2148 usaremos una interfaz JTAG.
Se ha seleccionado la interfaz Olimex JTAG USB por su bajo costo, compatibilidad con
el resto de herramientas, y versatilidad, ya que además de servirnos como interfaz
JTAG incluye un regulador de DC que puede proporcionar una tensión seleccionable de
5,9 o 12 voltios, lo que permite utilizar la placa de desarrollo sin necesidad de emplear
una fuente de alimentación adicional. En cualquier caso tendremos que tener en
cuenta que para algunas aplicaciones este regulador no podrá proporcionarnos la
potencia necesario, ya que la corriente máxima que entrega es de 200mA a 5V,
además de no ofrecer una regulación muy buena, por lo que para aplicaciones
sensibles a la tensión de alimentación será necesario usar una fuente de alimentación
convenientemente regulada.
Adicionalmente esta interfaz proporciona un puerto serie RS232, muy conveniente, ya
que los PCs actuales no suelen incorporarlo.
43
Figura 15 Interfaz JTAG
Esta interfaz JTAG de esta basada en el chip FTDI FT223211, que está específicamente
soportado por OpenOCD.
4.3.6 HIGH INTEGRITY STAVIEWER PLUGGIN
Este plugin, desarrollado por High Integrity Systems, que es la compañía que ofrece
soporte comercial y versiones certificables de FreeRTOS, permite inspeccionar durante
la depuración el estado de las tareas, colas de mensajes y semáforos de nuestra
aplicación.
La instalación de este plugin en Eclipse bajo Linux no está directamente soportada por
el fabricante, por lo que para hacerlo hay que seguir un procedimiento especial.
El paquete de distribución de este plugin es un instalador para Windows, sin embargo,
el plugin en sí mismo es una aplicación Java.
Para poder instalarlo en Eclipse bajo Linux, primero tendremos que ejecutar el
instalador bajo Windows, que creará una carpeta de instalación en la que tendremos
acceso al manual y a los módulos Java que componen el plugin.
Dentro de la ruta de instalación en Windows, en la carpeta plugins, encontramos el
modulo Java en cuestión:
11 http://www.ftdichip.com
44
Figura 16 Instalación de STATEVIEWER
Procedemos a copiar toda la carpeta de instalación de Windows a nuestra máquina
Linux.
Para instalar el plugin, en el menú Help de Eclipse seleccionamos “Install New
Software”, y en el cuadro de diálogo que aparece presionamos el botón Add. Nos
mostrará un nuevo cuadro de diálogo en el que debemos introducir el nombre del
plugin y la ruta de la carpeta que previamente hemos copiado. En este momento nos
listará el plugin como disponible para su instalación:
Figura 17 Instalación de plgin en Eclipse
45
A partir de este momento solo tenemos que seguir el asistente de instalación y
reiniciar Eclipse al final del proceso.
A partir de este momento, tendremos dos nuevas vistas disponibles en el menú
Window->ShowView->Other:
Figura 18 Selección de las vista de depuración del FreeRTOS
Como se puede observar, tras la instalación disponemos de dos vistas nuevas: Queue
table y Task table.
Queue table mostrará información sobre las colas de mensajes y semáforos que
usemos en la aplicación. Es una vista tabular con las siguientes columnas:
• Name: nombre de la cola o semáforo
• Address: dirección de la estructura que mantiene la cola o semáforo.
• Max Length: máximo número de elementos que puede alojar la cola.
• Item size: tamaño de cada elemento de la cola en bytes.
• Current Length: número de elementos almacenados actualmente en la cola.
• #Waiting Tx: número de tareas que hay bloqueadas esperando que la cola esté
disponible para escritura.
• #Waiting Rx: número de tareas que hay bloqueadas esperando mensajes de la
cola.
46
Figura 19 Tabla de colas de mensajes
Task table es otra vista tabular, pero esta, como su nombre indica, mostrará
información sobre el estado de ejecución de las tareas. Está compuesta por las
siguientes columnas:
• Task Name: el nombre de la tarea.
• Task Number: ID único asignado por el kernel a la tarea.
• Priority/actual: prioridad efectiva que posee actualmente la tarea. Esta puede
ser distinta que la prioridad base debido al mecanismo de herencia de
prioridad.
• Priority/base: prioridad base de la tarea.
• Start of stack: dirección base del stack asignado a la tarea.
• Top of stack: dirección de la última inserción en el stack.
• State: estado de ejecución de la tarea.
• Event object: nombre o dirección del objeto de sincronización que está
bloqueando la tarea.
• Min free stack: esta columna permite calcular la “High water mark” que es el
mínimo número de bytes que ha habido libres en el stack durante la ejecución.
Esta función es muy útil para dimensionar y optimizar el tamaño del stack
asignado a cada tarea, aunque no es conveniente tenerla siempre activa ya que
relentiza bastante la ejecución.
Figura 20 Tabla de tareas
47
4.4 CONCLUSIONES
Como se ha visto, es posible configurar un entorno completo de desarrollo para la
plataforma ARM usando software libre. El resultado es un entorno de desarrollo de
alta calidad, con todas las funciones que pueda ofrecer cualquier herramienta
comercial, y al estar virtualizado, fácilmente distribuible, facilitando las tareas de
mantenimiento de los puestos de desarrollo.
En las próximas secciones utilizaremos este entorno para desarrollar las aplicaciones
para el microcontrolador.
48
49
5 SISTEMAS OPERATIVOS EN TIEMPO REAL
5.1 INTRODUCCIÓN
Los sistemas de control modernos son generalmente sistemas complejos en los cuales
intervienen diversos módulos que cooperan entre sí para realizar la acción de control.
Estos módulos suelen tener restricciones temporales en su ejecución, así como fuertes
relaciones con los demás módulos del sistema.
Si bien existen técnicas clásicas para la implementación de sistemas de control en
tiempo real, el uso de un sistema operativo dedicado a tal efecto simplifica en buena
medida el proceso de implementación, limitando las dependencias con el hardware y
proporcionando mecanismos de temporización, comunicaciones y sincronización de
procesos que permiten al desarrollador centrarse en la funcionalidad y no tener que
preocuparse por implementar el mismo de forma correcta esos mecanismos.
Algunas características deseables para un sistema operativo en tiempo real son:
• Determinismo temporal en la ejecución de procesos.
• Baja latencia en la atención a interrupciones.
• Baja latencia en la conmutación de procesos.
En el contexto de los sistemas basados en microcontrolador, a los requisitos usuales de
los sistemas operativos en tiempo real hay que añadir algunos específicos debido a la
limitación de recursos de estos sistemas, en concreto por la carencia de unidad de
gestión de memoria (MMU) y especialmente por la escasez de memoria RAM.
En los apartados siguientes revisaremos algunos conceptos fundamentales en los
sistemas operativos de tiempo real.
5.2 MULTITAREA
El kernel es el módulo fundamental en un sistema operativo; en los sistemas
operativos multitarea, se encarga de la gestión de las tareas en ejecución.
El kernel proporciona mecanismos para la ejecución de múltiples tareas
simultáneamente y para la sincronización y comunicación entre ellas.
El uso de un sistema operativo multitarea puede facilitar la implementación de
sistemas complejos:
• Actividades complejas pueden descomponerse en tareas más simples.
50
• Los mecanismos de temporización son gestionados por el sistema
operativo.
• El particionado en procesos puede hacer más fáciles las pruebas del
software.
5.3 MULTAREA Y CONCURRENCIA
Los procesadores con un solo núcleo únicamente pueden ejecutar una tarea en un
instante de tiempo determinado, pero si conmutamos las tereas en ejecución
rápidamente, podemos hacer que se comporte como si realmente se ejecutaran de
forma concurrente.
En un microcontrolador con un solo núcleo, solo podrá ejecutarse una única tarea. El
kernel decide que tarea debe ejecutarse comprobando la prioridad de cada tarea.
En microcontroladores con varios núcleos, como las familias Renesas SH72x5l o la
familia Propeller de Paralax, podemos conseguir la ejecución concurrente real
(multiprocesamiento simétrico) de tantos procesos como CPUs integre el
microcontrolador.
5.4 EL PLANIFICADOR
El planificador es el componente del kernel que decide que tarea se ejecuta en cada
instante de tiempo. La decisión de que tarea es la que se ejecuta se hace conforme a la
política de planificación usada por el planificador.
Una tarea puede ser suspendida por el kernel, pero también puede suspenderse a sí
misma, por ejemplo si quiere esperar un determinado tiempo o esperar que un
recurso esté disponible. Una tarea suspendida no requiere tiempo de procesamiento,
con lo que el planificador puede poner en ejecución otra tarea.
Cuando una tarea está en ejecución, utiliza los registros de la CPU y accede a la RAM
como cualquier programa. Estos recursos representan el contexto de ejecución de una
tarea.
Cuando el kernel suspende una tarea, es necesario que se guarde este contexto de
ejecución, ya que cuando se vuelva a ejecutar la misma tarea, este contexto debe ser
restaurado al estado inmediatamente anterior a la suspensión.
Al proceso de guardar el contexto de una tarea y restaurar el contexto de una tarea
que pase a ejecutarse se le llama cambio de contexto.
51
5.4.1 APLICACIONES DE TIEMPO REAL
Los sistemas operativos de tiempo real se basan fundamentalmente en los principio
comentados anteriormente, pero con el objetivo concreto de hacer que los sistemas
tengan un tiempo de respuesta predecible ante determinados eventos.
Normalmente cuando se afronta el diseño de un sistema en tiempo real que debe
responder a eventos externos, se presenta una limitación en el tiempo de respuesta a
los eventos, de forma que el sistema debe responder antes de dicho límite de tiempo,
llamado deadline, para que el resultado sea válido.
Figura 21 Deadline de procesamiento
La respuesta al estímulo puede ser síncrona o asíncrona, pero en cualquier caso,
debemos asegurar la respuesta dentro del deadline.
La siguiente figura ilustra el comportamiento de una tarea síncrona o periódica:
Figura 22 Ejecución síncrona
Esta aproximación permite efectuar el procesamiento requerido con una periodicidad
fija, de forma que en el peor caso aseguramos la atención a la ocurrencia de un evento
en un tiempo igual a dos periodos.
La siguiente figura muestra el comportamiento de una terea asíncrona:
52
Figura 23 Ejecución asíncrona
Esta aproximación puede usarse si el proceso está estrictamente vinculado al tiempo
en el que ocurre el evento, de esta forma podemos asegurar el procesamiento ante un
evento dentro de un deadline a partir de la ocurrencia del mismo.
Para alcanzar este objetivo, el desarrollador debe asignar prioridades a las distintas
tareas, de forma que se asegure la ejecución prioritaria de las tareas con mayores
restricciones temporales.
Consideremos el siguiente ejemplo:
Se está implementando un ecualizador de audio. El sistema realiza el filtrado de una
señal muestreada en función de los controles manipulables por el operador del
equipo.
La lectura de los controles la realiza la siguiente función:
void vTareaLeerControles(void *pvParameters)
{
for(;;)
{
[esperar 1/100 segundos]
[leer controles]
[calcular coeficientes de los filtros]
}
}
El filtrado lo realiza la siguiente función: void vTareaFiltrado(void *pvParameters)
{
for(;;)
{
[esperar 1/44100 segundos]
[tomar muestra]
[filtrar]
[escribir muestra en CDA]
}
}
Listado 1 Procesado de audio en tiempo real
53
El sistema tiene la siguiente restricción:
El procesado de ninguna muestra puede retrasarse más de 1/44100 segundos, ya que
provocaría un efecto audible.
Para asignar prioridades a las tareas tendremos en cuanta lo siguiente:
• El deadline de la tarea de filtrado es más estricto que la de control de
usuario.
• Las consecuencias de la pérdida del deadline de la tarea de filtrado no
es tolerable.
Por tanto se asignará una mayor prioridad a la tarea de filtrado.
54
55
6 FREE RTOS
6.1 INTRODUCCIÓN A FREERTOS.
FreeRTOS es un Kernel de tiempo real gratuito y de fuentes abiertas. Esta desarrollado
y soportado por la compañía High Integrity Systems, que ofrece soporte y versiones
comerciales y certificables (OpenRTOS y SafeRTOS12) del mismo, de las cuales Texas
Instruments comercializa un dispositivo con SafeRTOS pregrabado en ROM.
Adicionalmente, está soportado por una amplia comunidad de desarrolladores, siendo
quizás el sistema operativo de tiempo real más ampliamente usado de su categoría.
Este SO se ha portado a múltiples arquitecturas y herramientas de desarrollo.
El SO se puede considerar de tipo microkernel, ya que no ofrece más que un
planificador y una API de comunicación entre procesos. No obstante, proporciona
mecanismos suficientes para poder implementar mecanismos de abstracción de
hardware, como drivers de dispositivos, que en el caso de FreeRTOS no son más que
un proceso convencional dedicado a tal propósito y quizás las rutinas de interrupción
vinculadas al hardware a abstraer.
FreeRTOS es especialmente apropiado para ser usado en sistemas embebidos basados
en microcontroladores con recursos limitados, en la que otras opciones como QNX,
Integrity o VxWorks no son viables.
Añade un overhead de procesamiento mínimo, así como un consumo de memoria
muy bajo; el kernel solo requiere entre 4 y 9 KB según la configuración.
El planificador puede configurarse para funcionar de forma expropiativa, cooperativa e
hibrida, así mismo permite el uso de procesos, corrutinas o ambos mecanismos a la
vez.
También proporciona mecanismos de traza de ejecución y optimización.
6.1.1 MULTIPROCESAMIENTO EN SISTEMAS EMBEBIDOS PEQUEÑOS.
Existen métodos altamente efectivos para diseñar software para sistemas embebidos
sin necesidad de usar un RTOS, como puede ser mediante la implementación de
máquinas de estados. Para los sistemas más sencillos prescindir de un RTOS puede
12Precertificado IEC61508 SIL3, FDA510(k) Class III y EN62304, cualificable para DO-178B.
56
resultar la mejor opción, sin embargo, según aumenta la complejidad del sistema a
implementar, las ventajas de usar un RTOS se hacen evidentes.
Como se ha comentado anteriormente, la priorización de tareas puede ayudar a
conseguir que la aplicación cumpla con los deadlines, pero el uso de un kernel
proporciona otros beneficios que aunque inicialmente no son tan obvios, presentan
enormes ventajas frente a la no utilización de un RTOS:
• Abstracción del comportamiento temporal:
El kernel es responsable de la temporización y proporciona una API para
este propósito.
• Mantenibilidad / Extensibilidad:
Al abstraer los detalles de temporización resulta en una reducción de las
dependencias entre distintos módulos, lo que permite aumentar el
aislamiento de cada componente software. Así mismo, al encargarse el
SO de la temporización, conseguimos abstraer las dependencias
temporales con respecto al hardware empleado, lo que mejora la
portabilidad de la solución.
• Modularidad:
Por definición, cada tarea es independiente. Esto también implica una
facilidad añadida para el desarrollo en equipo y las pruebas.
• Reutilizabilidad del código:
Debido a la modularidad e independencia de cada tarea, puede ser
sencillo reutilizarlas en otras aplicaciones.
• Mejora de la eficiencia:
En aplicaciones complejas, resulta realmente difícil hacerlas dirigidas por
eventos de una forma eficiente, así como eliminar por completo las
esperas activas y pollings.
FreeRTOS proporciona todos los servicios necesarios para que los
procesos sean completamente dirigidos por eventos, el precio a pagar
es un ligero impacto al tenerse que ejecutar el código del kernel.
57
• Gestión del tiempo improductivo:
Mediante la tarea Idle, podemos usar el tiempo en el que no se está
ejecutando ninguna tarea para diversos, como por ejemplo, poner el
microcontrolador en modo de bajo consumo.
• Manejo de interrupciones más flexible:
Pueden mantenerse los tiempos de atención a interrupciones muy bajos
haciendo que el procesamiento se haga mediante una tarea designada,
fuera de la propia RTI.
• Acceso a los periféricos seguro y simplificado:
Es posible codificar tareas encargadas de la gestión y acceso a los
periféricos, de forma similar a un driver. Estos drivers son fácilmente
reutilizables en otros proyectos.
6.2 EL PLANIFICADOR
En FreeRTOS los procesos se implementan mediante funciones en C. Para que una
función pueda ser manejada como un proceso debe tener el siguiente prototipo:
Void NombreDelProceso(void *pvParametros)
Un proceso no debe salir de su función de implementación nunca, es decir, nunca
contendrán una función return. Para la destrucción de procesos siempre han de usarse
las funciones para tal propósito de la API de FreeRTOS.
Cada proceso podemos considerarlo como un programa independiente, cuyo punto de
entrada es la función que implementa el proceso.
Es posible ejecutar varias instancias del mismo proceso, en ese caso, cada instancia
posee su propio contexto de ejecución.
6.2.1 GESTIÓN DE PROCESOS
En un sistema con un solo procesador, como es el caso del LPC2148, solamente una
tarea podrá ejecutarse en un determinado instante de tiempo. El conjunto de tareas
que componen el sistema podrán estar en dos estados principales: en ejecución o no
en ejecución.
Las tareas que no están en ejecución, a su vez pueden estar en distintos estados:
suspendida, bloqueada o preparada.
58
Una tarea prepara está lista para proseguir su ejecución. Estas tareas están a la espera
de que el planificador les asigne la CPU.
Una tarea bloqueada está a la espera de algún evento, como puede ser que un
semáforo se libera, la recepción de un mensaje desde una cola de mensajes o a la
espera de que pase un determinado tiempo.
Una tarea suspendida no es tenida en cuenta por el planificador, pero podría
continuarse su ejecución ya que la tarea sigue existiendo, así como su stack y su último
contexto de ejecución. En FreeRTOS la suspensión de tareas tiene que ser explícita, así
como su continuación.
En el siguiente diagrama pueden observarse los diferentes estado en los que pueden
estar las tareas en FreeRTOS(), así como las condiciones o funciones que provocan las
transiciones entre estados:
Figura 24 Estados de los procesos
6.2.1.1 ALGORITMO DE PLANIFICACIÓN DE FREERTOS
FreeRTOS utiliza un algoritmo de planificación expropiativa de prioridad fija. Con
prioridad fija nos referimos a que la prioridad de cada proceso nunca es modificada
por el planificador. Es expropiativa ya que un proceso que este en estado Preparado
59
siempre expropiara la ejecución si el proceso en ejecución tiene una prioridad inferior
a él.
Los procesos pueden esperar en el estado bloqueado a que ocurra un evento, en ese
momento pasaran a estado Preparado.
Cuando varios procesos con la misma prioridad están en estado preparado, su
ejecución será tipo round robbin, asignado a cada proceso slice de un tamaño igual a
un tick del sistema.
En el siguiente diagrama se ilustra el comportamiento de una aplicación:
Proceso 1
Proceso 2
Proceso 3
Idle
T1 T2 T
3
T4 T5 T6 T
7
T
8
T9 T10
Figura 25 Ejemplo de planificación de procesos
Proceso 1: prioridad alta, espera evento
Proceso 2: prioridad media, ejecución periódica
Proceso 3: prioridad baja, espera evento
Idle: proceso de más baja prioridad, se ejecuta de forma continua
En T1 este es el estado de ejecución:
Proceso 1: bloqueado, espera la ocurrencia de un evento.
Proceso 2: en ejecución.
Proceso 3: bloqueado, espera la ocurrencia de un evento.
Idle: no está en ejecución ya que el Proceso 2 tiene mayor prioridad.
En T2 Proceso 2 completa su ejecución y pasa a bloqueado, los procesos 1 y 3 siguen
bloqueados, Idle pasa a ejecutarse.
En T3 se produce el evento que espera el proceso 3, con lo que pasa a preparado e
inmediatamente expropia la ejecución a Idle.
60
En T4 el proceso 3 termina su ejecución, como los procesos 2 y 3 siguen bloqueados,
por lo que Idle pasa a ejecutarse.
En T5 se produce otra vez el evento que espera el proceso 3, pasando a preparado e
inmediatamente expropiando la ejecución a Idle.
En T6 expira el periodo de ejecución del proceso 2, pasando este a preparado. Al tener
mayor prioridad que proceso 3, pasa a ejecución, quedando el proceso 3 en
preparado.
En T7 ocurre el evento que espera T1, con lo que pasa a preparado, y al tener mayor
prioridad que el proceso 2, pasa a ejecución, quedando este en estado preparado.
En T8 el proceso 1 termina su ejecución, pasando a bloqueado a la espera de un nuevo
evento. El proceso 2 pasa a ejecución, al ser el de mayor prioridad de los procesos
preparados.
En T9 el proceso 2 termina su ejecución, pasando a bloqueado. El proceso 3 es
planificado al poseer mayor prioridad que Idle.
En T10 el proceso 3 termina su ejecución, pasando a bloqueado a la espera de un
nuevo evento. Al no haber ningún otro proceso preparado, Idle pasa a ejecución.
6.2.1.2 PLANIFICACIÓN COOPERATIVA
FreeRTOS puede configurarse para implementar una planificación cooperativa.
En un sistema operativo con planificación cooperativa, los cambios de contexto solo
ocurren cuando una tarea se bloquea a sí misma, o llama al planificador para que
reasigne la ejecución (median la función taskYIELD()). En este contexto, un proceso
nunca es expropiado de la ejecución por otros procesos. Tampoco se comparte el
tiempo de ejecución con procesos con la misma prioridad.
Aunque FreeRTOS puede configurarse para hacer una planificación cooperativa, en el
presente trabajo no se usará esta posibilidad. Una planificación cooperativa puede
resultar en una mayor eficiencia, pero requiere un diseño muy cuidado de la
aplicación, así como pruebas exhaustivas, ya que cualquier proceso podría bloquear
todo el sistema.
6.2.1.3 EL TICK DEL SISTEMA. GESTIÓN DEL TIEMPO
El kernel de FreeRTOS mide el tiempo usando una variable para contar ticks. Para
implementar tal mecanismo FreeRTOS utiliza un timer que genera una interrupción en
la que se incrementa dicho contador. La frecuencia de este temporizador es
configurable, y no permite ajustar con precisión la granularidad temporal del sistema.
61
Gracias a este mecanismo las funciones temporizadas de la API pueden hacer esperas
pasivas y timeouts, siempre en tiempos múltiplos del periodo del tick del sistema.
Cada vez que se incrementa el contador de ticks, el planificador comprueba si debe
desbloquear alguna tarea, lo que además puede provocar un cambio de contexto.
Obviamente este mecanismo nos obliga a prescindir de uno de los timers de propósito
general del microcontrolador, ya que debe ser para uso exclusivo del sistema
operativo.
6.2.1.4 CAMBIO DE CONTEXTO
Como sabemos, el contexto de ejecución de una tarea está compuesto por el conjunto
de registros que utiliza y su montículo. Al ser suspendida una tarea y planificado otra,
es imprescindible almacenar este contexto de ejecución para poder restaurarlo en el
momento en que se vuelva a ejecutar la tarea suspendida. En FreeRTOS, al usar un
mecanismo de planificación expropiativa, las tareas pueden ser suspendidas en
cualquier momento, por lo que al ser imprevisible por la propia tarea, el cambio de
contexto lo realiza el sistema operativo. En la CPU ARM7 el contexto de ejecución
consiste en los registros R0-R15 y el CPSR.
Como veremos más adelante, FreeRTOS implementa un mecanismo de gestión de
memoria para poder gestionar los montículos de los distintos procesos. El planificador
almacenará en el montículo de cada tarea su contexto de ejecución con el fin de
restaurarlo al proseguir la ejecución.
También encontraremos la necesidad de salvaguardar el contexto de ejecución de las
tareas cuando se ejecute una rutina de interrupción que pueda llevar a cabo un
cambio de contexto, ya sea directamente o al usar la API de IPC, lo que podría forzar al
planificador a cambiar de proceso en ejecución. Veremos este mecanismo en un
apartado dedicado.
6.2.2 CREACIÓN Y DESTRUCCIÓN DE TAREAS
En este apartado veremos el proceso de declaración, creación y ejecución de una
tarea.
Para que una tarea pueda ser panificable por FreeRTOS, esta debe ser implementada
en una función en C que implemente el siguiente prototipo:
void Tarea(void *pvParameters)
Cada tarea podremos considerarla como un programa en sí misma, independiente del
resto de tareas en ejecución.
62
Además de declarar la tarea, para que pueda ser planificable por el kernel, es
necesario que la creemos mediante la función de la API xTaskCreate, normalmente
esto se hará en la función main() del sistema o en otra tarea.
Normalmente una tarea incluye un bucle infinito, donde se lleva a cabo el
procesamiento. En este sentido, si bien una tarea no tiene porque ejecutarse de forma
indefinida, si hay que tener en cuenta que nunca debe retornar, es decir, nunca
intentar suspender su ejecución mediante un return. Si se desea terminar una tarea,
hay que destruirla específicamente con la función xTaskDelete() de la API de FreeRTOS,
esto puede hacerse desde la propia tarea o desde otra tarea.
Por último, tendremos que inicial el planificador, que gestionará la ejecución de las
tareas creadas.
En el ejemplo “Proyecto Básico” incluido en el DVD adjunto puede verse un ejemplo de
este proceso.
6.3 GESTIÓN DEL MONTÍCULO
Como se ha comentado anteriormente, FreeRTOS necesita reservar memoria para
almacenar el contexto de ejecución de los distintos procesos, así como para almacenar
las estructuras usadas por semáforos y colas de mensajes. Para ello implementa tres
esquemas de gestión de memoria, que se adaptan a distintos requisitos que podamos
tener en nuestra aplicación.
ESQUEMA 1
Implementado en heap_1.c
Es el esquema más restrictivo. No permite liberar memoria, lo que restringe la reserva
de memoria dinámicamente. El algoritmo asigna memoria del montículo,
dimensionado estáticamente en el archivo de configuración de FreeRTOS mediante la
definición configTOTAL_HEAP_SIZE.
Este esquema solo es usable si no destruimos tareas, semáforos ni colas de mensajes.
Presenta la ventaja de que su ejecución es determinística.
ESQUEMA 2
Implementado en heap_2.c
Es un poco menos restrictivo que el anterior, en cuanto a que permite la liberación de
bloques de memoria, pero no reordena la memoria, lo que puede dar lugar a la
63
fragmentación del montículo, por lo que solo debe usarse cuando los bloques de
memoria a crear y eliminar sean del mismo tamaño, es decir, tareas con el mismo
tamaño de pila y colas de mensajes del mismo tamaño.
Otro inconveniente que presenta este esquema es que su ejecución no es
determinística.
ESQUEMA 3
Es el menos restrictivo, simplemente es un envoltorio que hace uso de las funciones
malloc() y free() encapsulándolas en una sección critica para protegerlas ante
eventuales cambios de contexto.
En este esquema la ejecución es no determinística.
En este proyecto incluiremos el esquema de gestión de memoria que mejor se adapte
a nuestras necesidades, pero en el contexto de microcontroladores con escasos
recursos de memoria RAM, en general suele ser más conveniente y seguro emplear el
esquema 1 siempre que la aplicación lo permita, así como hacer el software
completamente estático, prescindiendo del uso de memoria dinámica.
6.4 USO DE LA PILA
Como se comentó anteriormente, cada tarea posee su propia pila. La memoria usada
por la pila de cada tarea se reserva automáticamente al crear la tarea con la dimensión
especificada. Averiguar el tamaño óptimo de la pila no es un proceso sencillo, pero
FreeRTOS proporciona varios mecanismos para poder llevar a cavo esta tarea.
El más sencillo puede ser utilizar el Stateviewer plugin para ver el espacio mínimo
disponible, e ir aumentando el tamaño del stack si llegamos a quedarnos sin memoria.
También podemos comprobar en tiempo de ejecución si ocurre un desbordamiento de
pila mediante la definición de configuración configCHECK_FOR_STACK_OVERFLOW.
Mediante esta configuración podemos definir una función gancho con el siguiente
prototipo:
void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed
portCHAR *pcTaskName );
Esta función será ejecutada cuando se desborde la pila. El parámetro pxTask es un
puntero al manejador de la tarea que ha causado el desbordamiento, y pcTaskName es
el nombre de dicha tarea.
64
Internamente, FreeRTOS puede implementar dos métodos para detectar el
desbordamiento de la pila:
MÉTODO 1
FreeRTOS al quitar de ejecución a una tarea, que supone que es el momento en que la
pila está más ocupada al contener todo el contexto de ejecución del proceso,
comprueba si el puntero de pila está dentro del rango permitido.
Para usar este método hay que definir la configuración a 1.
MÉTODO 2
En este método es complementario al 1 y lo que se hace es escribir todo el stack con
un valor conocido y fijo. Ahora lo que se comprueba tras el cambio de contexto es el
valor de los 16 últimos valores de la memoria reservada al stack para ver si se han
sobrescrito.
Para usar este método, definiremos la configuración a 2.
6.5 MECANISMOS DE COMUNICACIÓN ENTRE PROCESOS (IPC)
FreeRTOS implementa una API de IPC básica, que incluye los siguientes mecanismos de
comunicación entre procesos y sincronización:
• Colas de mensajes.
• Semáforos binarios.
• Semáforos contadores.
• Mutex.
• Mutex recursivos.
Semáforos binarios.
Su aplicación típica es la de sincronización de procesos.
La implementación de FreeRTOS de los semáforos binarios tiene las siguientes
características:
• No implementa herencia de prioridad.
• Implementa un mecanismo de timeout de espera.
Hay que notar, que hay la API consta de métodos para la manipulación de semáforos
diferenciados de si la operación se hace o no desde una interrupción.
65
SEMÁFOROS CONTADORES.
Su aplicación típica es la cuenta de eventos y la gestión de recursos.
Los semáforos contadores también implementan un mecanismo de timeout, y al igual
que los semáforos binarios, cuenta con funciones específicas para su manipulación
desde rutinas de interrupción.
MUTEX.
Son básicamente una implementación de los semáforos binarios con un mecanismo
de herencia de prioridad. Este mecanismo hace que si una tarea de baja prioridad T1
está ocupando un recurso, y una tarea de mayor prioridad T2 intenta acceder a este, la
prioridad de T1 se eleva a la de T2, con el fin de que el recurso se libere lo antes
posible para que está disponible para T2.
MUTEX RECURSIVOS.
No es más que un mutex que se puede tomar varias veces por el propietario del
recurso. El propietario también deberá liberarlo tantas veces como lo haya tomado
previamente.
Hay que tener en cuenta que no es posible usar ningún tipo de mutex desde una rutina
de interrupción.
COLAS DE MENSAJES.
El comportamiento de las colas de mensajes en FreeRTOS es tipo FIFO, y pueden
contener elementos de cualquier tipo de tamaño fijo, que son insertados por copia en
la cola, por lo que habrá que tener cuidado en la elección de los tipos para los
mensajes.
De igual forma que los otros mecanismos de IPC, las colas de mensajes implementan
un timeout para las operaciones. También existen un conjunto de funciones
específicas para su manejo desde rutinas de interrupción.
6.6 RUTINAS DE INTERRUPCIÓN.
FreeRTOS no impone ninguna estrategia en cuanto al procesado de interrupciones, en
este sentido, podemos elegir entre hacer el procesamiento desde dentro de la propia
rutina de interrupción o desde un proceso externo delegado, al que indicaremos la
ocurrencia del evento mediante un semáforo o una cola de mensajes.
66
Si hay que tener muy presente que dentro de una rutina de interrupción solo podemos
llamar a las funciones de la API y macros que terminan en “FromISR” o en “FROM_ISR”.
Aunque como hemos comentado antes, FreeRTOS no impone ninguna estrategia en la
atención a las interrupciones, es recomendable, siempre que las restricciones
temporales lo permitan, usar un proceso delegado, para intentar tener tiempos de
ejecución de las rutinas de interrupción lo más bajos posibles.
La técnica consiste en hacer el mínimo procesado dentro de la interrupción, por
ejemplo guardar el valor de una lectura del conversor A/D, o un byte recibido en una
UART (puede verse un ejemplo de esto en la implementación del driver de la UART), y
avisar mediante algún mecanismo de IPC, como pueda ser una cola de mensajes o un
semáforo, a un proceso encargado de efectuar el procesamiento adicional.
Es importante tener en cuenta algunos detalles a la hora de codificar una rutina de
interrupción que pueda provocar un cambio de contexto.
Siempre que usemos las funciones de IPC dentro de una rutina de interrupción
tendremos que insertar las macros portENTER_SWITCHING_ISR y
portEXIT_SWITCHING_ISR al principio y al final de la rutina de interrupción.
La macro portENTER_SWITCHING_ISR fuerzan la salvaguarda del contexto de
ejecución de la tarea interrumpida, y portEXIT_SWITCHING_ISR hace que se cambié de
contexto a una nueva tarea si el planificador así lo requiere por las operaciones
efectuadas dentro de la RTI.
Así mismo, el mecanismo de codificación de rutinas de interrupción exige seguir un
patrón concreto para evitar problemas con distintas versiones de GCC y opciones de
compilación.
La entrada a la rutina de interrupción se hace a través de una función adaptadora que
permite implementar una interfaz compatible con el compilador. El siguiente listado
ilustra el proceso:
//Declaramos la función envoltorio con el atributo naked void ISR_Wrapper ( void ) __attribute__ ((naked)); /* * La función envoltorio es el punto de entrada de la RTI * Salva el contexto de ejecución de la tarea interrumpida * Llama a la función donde se implementa el código de tratamiento de la interrupción * Finalmente restaura el contexto de ejecución apropiado */ void ISR_Wrapper ( void ) { portENTER_SWITCHING_ISR (); portBASE_TYPE xTaskWoken = pdFALSE;
67
xTaskWoken=ISR(); portEXIT_SWITCHING_ISR (xTaskWoken); } /* * Esta será la función que efectúe el tratamiento de la interrupción * devolverá pdTRUE si algún proceso a pasado a preparado dentro de la rutina * pdFALSE en otro caso */ portBASE_TYPE ISR (void ) { portBASE_TYPE xTaskWoken; //código de la RTI return (xTaskWoken);
}
Listado 2 Codificación de rutina de interrupción
6.6.1 ABSTRACCIÓN DE HARDWARE MEDIANTE DRIVERS.
Un mecanismo que simplifica las operaciones de E/S, mejora el desacoplamiento entre
módulos, y además fácilmente reutilizable, es la abstracción del los periféricos
mediante drivers.
Aunque el concepto de driver no existe en FreeRTOS, dentro de la comunidad de
desarrolladores se utiliza este término para referirse a un conjunto de rutinas y
estructuras que permiten la abstracción de un determinado periférico.
En FreeRTOS no hay una API o interfaz definida para los drivers, pero en general la
implementación suele hacerse de la siguiente forma:
• Se define algún mecanismo de IPC para indicar la ocurrencia de un evento,
generalmente una cola de mensajes si el periférico genera datos, como por
ejemplo la recepción de un byte por parte de la UART o la captura de una
muestra en el conversor AD. Normalmente, el proceso que espera un dato de
un periférico se bloqueará esperando datos de la cola de mensajes recibida.
• Se define algún mecanismo IPC para efectuar operaciones de salida,
generalmente una cola de mensajes, como por ejemplo, el ciclo de trabajo del
modulador PWM, un byte a transmitir por la UART, etc. Cuando una tarea
quiere escribir datos en un periférico, solo tiene que enviar el tipo de datos
adecuado por la cola del periférico. Normalmente, si se dimensiona bien el
tamaño de las colas y el periférico es relativamente rápido, esta operación no
bloqueará a la tarea.
68
• Se implementa la RTI del periférico, en la que se generan los mensajes IPC
correspondientes ante la disponibilidad de datos nuevos y se procesan las colas
de salidas.
En el capítulo 7 puede verse como ejemplo la implementación de un driver para las
UARTs.
6.7 ESTRUCTURA Y COMPONENTES DE UN PROYECTO CON FREERTOS.
En este punto veremos cómo está estructurado el código fuente de FreeRTOS y los
proyectos de ejemplos que lo acompañan. Más adelante veremos la estructura típica
de un proyecto de Eclipse con FreeRTOS.
6.7.1 ESTRUCTURA DEL CÓDIGO FUENTE DE FREERTOS
El archivo de distribución de FreeRTOS contiene el código fuente del SO, incluyendo
archivos específicos para todas las plataformas soportadas, también incluye
aplicaciones de demostración para muchas de estas plataformas así como una carpeta
adicional con los ports correspondientes a plataformas no soportadas oficialmente, si
no que son contribuciones de usuarios de FreeRTOS.
Partiendo del directorio raíz de FreeRTOS encontramos tres carpetas principales:
License: incluye la documentación de la licencia de FreeRTOS.
Source: esta carpeta contiene el código fuente de FreeRTOS
Demo: aquí se incluyen las demos para las distintas plataformas así como el código
fuente de las demos y ports no soportadas oficialmente.
69
Figura 26 Directorio de FreeRTOS
Como hemos comentado, la carpeta Source contiene todo el código fuente de
FreeRTOS. Su contenido se muestra en la siguiente captura de pantalla:
Figura 27 Carpeta Source de FreeRTOS
El código fuente de FreeRTOS consta de dos partes, una común a todas las
plataformas, y que constituye la mayor parte del núcleo del SO, compuesta por los
archivos task.c, list.c y qeue.c, contenidos en la misma carpeta Source.
La otra parte es código específico para cada compilador y cada plataforma soportada,
contenida en el directorio portable.
70
El código portable consta básicamente de las funciones de más bajo nivel requeridas
por el SO para llevar a cavo tareas como salvar el contexto de ejecución y detalles de la
implementación de los mecanismos de IPC y secciones críticas.
La siguiente captura muestra el contenido de la carpeta portable, en la que hay una
carpeta por cada compilador soportado:
Figura 28 Carpeta portable de FreeRTOS
Como ejemplo, en la siguiente figura se muestra el contenido de la carpeta GCC, en la
que se puede observar que existe una carpeta por cada arquitectura soportada:
Figura 29 Carpeta GCC de FreeRTOS
71
En nuestro caso, el código específico correspondiente al LPC2148 está contenido en la
carpeta ARM7_LPC2000:
Figura 30 Port para LPC2xxx
Como se puede observar, el código específico se limita a los archivos port.c, portISR.c y
portmacro.h.
6.7.2 ESTRUCTURA DE UN PROYECTO CON FREERTOS
Un proyecto con FreeRTOS constara de uno o varios procesos y opcionalmente de
algunos drivers para periféricos.
Es conveniente siempre codificar cada proceso en archivos independientes, de esta
forma no solo aumentamos la legibilidad de la aplicación, sino que facilitamos la
reutilizabilidad de los procesos y/o drivers.
El siguiente diagrama recoge los módulos, dependencias y responsabilidades de un
hipotético sistema con un solo proceso y un driver:
72
Figura 31 Diagrama de sistema con FreeRTOS
En este punto veremos los pasos a seguir para crear un proyecto nuevo en Eclipse con
FreeRTOS.
Aunque existe la posibilidad de crear un proyecto administrado, en el que el makefile
se gestiona automáticamente, resulta más práctico y menos propenso a errores utilizar
proyectos no administrados y modificar los makefiles manualmente.
El primer paso será crear un nuevo proyecto vacío no administrado de C en Eclipse.
Crearemos un makefile para el proyecto, o mejor, reutilizaremos convenientemente
modificado uno que ya tengamos de otro proyecto.
Importaremos una copia del archivo FreeRTOSConfig.h, que posteriormente
personalizaremos para el proyecto.
Configuraremos el makefile para incluir la carpeta ./FreeRTOS/Source/include, así
como la propia carpeta del proyecto.
Añadimos los siguientes archivos en el makefile:
• task.c
• queue.c
• list.c
• port.c
73
En cada uno de nuestros archivos de código que use la API de FreeRTOS, tendremos
que incluir el archivo “FreeRTOS.h”, y además el archivo de cabecera que contenga los
prototipos de la API que usemos:
• task.h: funciones de manipulación de procesos y depuración.
• queue.h: funciones de manejo de colas de mensajes.
• semphr.h: funciones de manejo de semáforos y mutes.
Adicionalmente, tendremos que incluir los archivos con las definiciones de registros
del LPC2148.
En DVD adjunto se incluye un proyecto básico de Eclipse con FreeRTOS que puede
utilizarse como punto de partida para otros proyectos.
6.7.2.1 ESTRUCTURA DE LA FUNCIÓN MAIN. BUCLE DEL SISTEMA.
En un proyecto con FreeRTOS, normalmente la función main() es responsable de las
siguientes acciones:
• Inicializar el hardware.
• Inicializar y configurar los drivers.
• Inicializar las estructuras de datos usadas por las tareas, como semáforos, colas
de mensajes, memoria compartida, etc.
• Crear las tareas.
• Inicializar el planificador.
Es notable la no existencia de un bucle del sistema, ya que está función la desempaña
el planificador. Será en cada una de las tareas donde se ubicará este bucle.
En el CD que adjunto a este documento, puede encontrarse como ejemplo un proyecto
mínimo en es que se ilustra este proceso.
6.8 CONFIGURACIÓN Y OPTIMIZACIÓN.
Como se ha comentado en puntos anteriores, FreeRTOS permite configurar un
conjunto de parámetros para optimizar el sistema operativo al contexto de nuestra
aplicación.
El número de parámetros es una lista larga, que está bien documentada, por lo que
nos limitaremos a comentar los más importantes.
74
Esta parametrización se hace en el archivo FreeRTOSConfig.h, .que generalmente
situaremos junto a nuestro código fuente, ya que debe ser específico para cada
proyecto. En este archivo, cada parámetro de controla mediante una definición.
Aunque conviene conocer al detalle toda la lista de parámetros, los más importantes
son:
#define configUSE_PREEMPTION: definiendo a 1 este parámetro configuramos el
planificador para efectuar planificación expropiativa.
#define configUSE_CO_ROUTINES: definiendo a 1 este parámetro habilitaremos la API
de corrutinas.
#define configTICK_RATE_HZ: en este parámetro indicamos la frecuencia del tick del
sistema. Este parámetro define la granularidad de ejecución del planificador, y debe
ser elegido con sumo cuidado porque todas las funciones temporizadas, como esperas
y timeouts de funciones, toman el tick del sistema como tiempo base, y solo pueden
efectuarse esperas de múltiplos enteros de este tiempo.
#define configTOTAL_HEAP_SIZE: es el tamaño de memoria disponible para el kernel
para el montículo.
#define configUSE_TRACE_FACILITY: definiendo a 1 este parámetro podemos utilizar
las macros gancho para trazar la ejecución de FreeRTOS. Este se verá con más detalle
en el siguiente apartado.
#define configCHECK_FOR_STACK_OVERFLOW: este parámetro permite implementar
un mecanismo para detector desbordamientos de la pila. Se explica detalladamente en
el punto 7.4.
6.8.1 MACROS DE TRAZA
Mediante las macros de traza podemos monitorizar la ejecución de FreeRTOS. El
mecanismo se basa en una serie de macros, inicialmente vacías, en el código de
FreeRTOS. Mediante la definición de estás macros, podemos llevar a cabo alguna
acción ante muchos eventos y/o cambios de estados del kernel y/o colas y semáforos.
Como ejemplo, podemos insertar código en las macros para enviar información por un
puerto serie (por ejemplo, el evento que ha ocurrido), establecer determinados valores
en el conversor DA o en las salidas digitales (por ejemplo para indicar que proceso está
en ejecución).
75
La lista de macros gancho es amplia, hay macros definidas para todos los eventos y
cambios de estado de FreeRTOS. La lista completa de macros está documentada en el
sitio web de FreeRTOS.
Para la definición de macros de traza solo hay que tener en cuenta un par de
consideraciones:
• Las macros en ocasiones pueden ejecutarse desde una RTI, por lo que deben
ser muy rápidas para tener el menor impacto posible en el rendimiento de la
aplicación.
• La definición de las macros debe hacerse antes de la inclusión de FreeRTOS.h,
siendo recomendable hacerlo en un archivo .h que posteriormente se incluirá
al final de FreeRTOSConfig.h.
6.9 CONCLUSIONES
Tras estudiar las características y API de FreeRTOS, podemos concluir que este sistema
operativo proporciona todas las funciones necesarias para el desarrollo de sistemas en
tiempo real, contando con una API sencilla y reducida. El soporte de múltiples
arquitecturas, así como la existencia de versiones comerciales y certificables,
representan una clara ventaja frente a otros sistemas operativos, vinculados a
plataformas o a herramientas de desarrollo completas.
También proporciona herramientas suficientes para la depuración y optimización de
las aplicaciones, así como una buena flexibilidad en su configuración.
El hecho de ser de código abierto favorece la implementación ports para nuevos
dispositivos y arquitecturas.
76
77
7 EJEMPLO DE SISTEMA DE CONTROL EN TIEMPO REAL: AUTOPILOTO PARA UAV
7.1 INTRODUCCIÓN
En esta sección veremos la implementación de un sistema de control medianamente
complejo partiendo de un diseño basado en modelos.
Analizaremos los requisitos temporales del controlador y mostraremos un método
para la verificación de la implementación mediante la inserción de sistema real en el
lazo de control simulado. A esta técnica se le suele llamar “Hardware in the loop” o de
forma abreviada HIL. Está técnica presenta algunas ventajas que hace que este
imponiéndose en los proceso de desarrollo de sistemas, ya que mediante ella se
simplifica considerablemente el proceso de validación y pruebas, ya que en general
podremos reutilizar de forma directa las pruebas realizadas sobre los modelos en el
entorno de simulación.
7.2 DISEÑO BASADO EN MODELOS
7.2.1 INTRODUCCIÓN
Una de las capacidades fundamentales de todo avión es que éste pueda moverse
siguiendo las órdenes de un piloto o un sistema que se encargan de generar las
consignas que se desean seguir. El sistema de control del avión sobre sus tres ejes fue
una de las contribuciones de los hermanos Wright, y ya entonces, su Flyer disponía de
timón de profundidad, timón de dirección y de un sistema de torsión de las alas que
producía el alabeo.
Las superficies de mando y control modifican la aerodinámica del avión provocando un
desequilibrio de fuerzas permitiendo que una o más de ellas cambien de magnitud.
Este desequilibrio, es lo que hace que el avión se mueva sobre uno o más de sus ejes,
incremente la sustentación, o aumente la resistencia.
En la figura se pueden observar los tres ejes de un avión y los movimientos sobre ellos.
Las superficies de control son principalmente tres: alerones, timón de profundidad
(elevador) y timón de dirección (rudder). A partir de estas superficies se pueden
combinaciones de ellas, como por ejemplo los elevons que serían la combinación del
elevador y los alerones.
En la siguiente figura se representa el esquema general del sistema. P
un generador de referencias, éste es el encargado de ind
quiera realizar y la referencia que quiere alcanzarse en él, estas consignan se
trasladarán al control de bajo nivel el cual tendrá como misión modificar las superficies
de control y el motor para llevar al avión al estado dese
Los controladores se han diseñado específicamente para el UAV Viewer
sistema aéreo de supervisión robusto, ligero y de fácil transporte, diseñado para
labores de Inteligencia, Observa
capacidad de carga de pago (2Kg) frente a su peso (8 Kg), manteniendo una propulsión
Figura 32 Ejes cuerpo de una aeronave
Las superficies de control son principalmente tres: alerones, timón de profundidad
(elevador) y timón de dirección (rudder). A partir de estas superficies se pueden
combinaciones de ellas, como por ejemplo los elevons que serían la combinación del
En la siguiente figura se representa el esquema general del sistema. Podemos observar
un generador de referencias, éste es el encargado de indicar el modo de vuelo que se
quiera realizar y la referencia que quiere alcanzarse en él, estas consignan se
trasladarán al control de bajo nivel el cual tendrá como misión modificar las superficies
de control y el motor para llevar al avión al estado deseado.
Figura 33 Diagrama de control de una aeronave
se han diseñado específicamente para el UAV Viewer
istema aéreo de supervisión robusto, ligero y de fácil transporte, diseñado para
Inteligencia, Observación y Reconocimiento. El Viewer destaca por su gran
capacidad de carga de pago (2Kg) frente a su peso (8 Kg), manteniendo una propulsión
78
Las superficies de control son principalmente tres: alerones, timón de profundidad
(elevador) y timón de dirección (rudder). A partir de estas superficies se pueden hacer
combinaciones de ellas, como por ejemplo los elevons que serían la combinación del
odemos observar
icar el modo de vuelo que se
quiera realizar y la referencia que quiere alcanzarse en él, estas consignan se
trasladarán al control de bajo nivel el cual tendrá como misión modificar las superficies
se han diseñado específicamente para el UAV Viewer. Se trata de un
istema aéreo de supervisión robusto, ligero y de fácil transporte, diseñado para
destaca por su gran
capacidad de carga de pago (2Kg) frente a su peso (8 Kg), manteniendo una propulsión
79
eléctrica tipo brushless de 1200 W de potencia con bajo impacto sonoro. Puede
realizar misiones de más de 1 hora de vuelo (autonomía de 75 a 90 minutos) con un
radio de acción de 45 km. Su altura operacional es de 300 metros y puede alcanzar
hasta 1500, su velocidad de operación está comprendida entre los 40 y los 110 km/h.
7.2.2 ESBOZO SOBRE ESTABILIDAD Y CONTROL DE LA AERONAVE
La estabilidad estudia el comportamiento del avión cuando una perturbación o entrada
de control lo separa de las condiciones de equilibrio.
Dentro de la estabilidad podemos encontrar la estabilidad estática, la cual es el análisis
del sentido o signo del momento aerodinámico total que desarrolla el avión después
de separarse de las condiciones de equilibrio y que según la respuesta podrá ser:
-Estable: el avión por si mismo desarrolla los momentos aerodinámicos necesarios
para retornar a la situación primitiva de equilibrio.
-Inestable: los momentos desarrollados tienden a separar al avión de la condición de
equilibrio.
-Neutro: el avión estará en equilibrio en esta nueva situación.
Otro tipo de estabilidad es la dinámica, ésta estudia el tipo de movimiento oscilatorio a
que darán lugar a lo largo del tiempo los momentos desarrollados por el avión.
Cuando el avión se separa del equilibrio y es estáticamente estable, oscilará sobre la
situación inicial, aunque esto no es suficiente para que vuelva al equilibrio ya que
según el efecto final existirán tres tipos de estabilidad dinámicas: convergente,
divergente e indiferente.
7.2.3 ESTABILIDAD Y CONTROL LONGITUDINAL
Se refiere al comportamiento del avión en sus movimientos de cabeceo (pitch)
alrededor del eje OY.
Para que exista estabilidad estática se deben desarrollar los momentos que lleven al
avión al punto de compensación, entendiéndose éste como el ángulo para el cual el
coeficiente del centro de gravedad es nulo. Por ejemplo, si el aire levantara el morro
del avión, se debería desarrollar un momento de picado que contrarrestara esto.
En cuanto a la estabilidad dinámica nos encontramos con dos posibles modos de
oscilación, siendo estos los autovalores de la matriz dinámica del avión:
-Phugoid Mode: es la pareja de polos complejos conjugados que tiene baja frecuencia
y consiste en una oscilación del orden de medio minuto y un tiempo de amortiguación
grande (minutos). En este tiempo el ángulo de ataque permanece constante y se
80
intercambia periódicamente energía cinética (velocidad) por energía potencial
(altitud).
-Short Period Mode: es la pareja de polos complejos conjugados con alta frecuencia y
consiste en un movimiento oscilatorio fuertemente amortiguado.
En la ilustración se puede ver un ejemplo de estos modos:
Figura 34 Modos de oscilación longitudinal
En lo referente al control, la actitud del avión en el cabeceo se consigue haciendo
aumentar o disminuir la sustentación que proporciona el conjunto horizontal de cola,
en este caso el elevador. Por ejemplo, cuando el elevador se desplaza hacia abajo se
genera sustentación hacia arriba subiendo la cola y transmitiendo un momento de
picado del avión.
7.2.4 ESTABILIDAD Y CONTROL LATERAL-DIRECCIONAL
Trata el comportamiento del avión en sus movimientos de alabeo y de guiñada. Debido
a que existe acoplamiento entre ambos se estudian conjuntamente y se puede
encontrar los siguientes modos:
-Divergencia espiral: este modo es muy rápido e inestable. Sucede cuando la
estabilidad direccional es mucho mayor que la lateral, el avión tiende a entrar en un
picado horizontal cada vez más pronunciado.
81
-Dutch Roll Mode (Balanceo del holandés): Este es modo con una gran oscilación en el
que todas las variables de la dinámica lateral oscilarán. En este caso predomina la
estabilidad lateral sobre la direccional, cualquier perturbación inicial de balanceo o
guiñada pone en juego una oscilación latero-direccional. Ambas frecuencias de las
oscilaciones son similares pero tienen un pequeño desfase en el que precede la lateral
a la direccional.
Existen otros modos pero no son tan comunes y estos dos son los más necesarios de
controlar.
La actitud perseguida se conseguirá mediante la deflexión asimétrica de los alerones.
Partiendo de la situación de crucero, si se alabea hacia la derecha se deben deflectar
los alerones para que baje el de la semiala izquierda, así aumenta su sustentación y, al
subir el del semiala derecha y bajar la sustentación de ésta, generar el momento
deseado.
7.2.5 ESBOZO DEL DISEÑO DEL CONTROLADOR DEL VIEWER
El proceso a través del cual se diseñaron los controladores del Viewer es el siguiente:
1) Se buscaron matemáticamente, mediante el estudio del lugar de las raíces en
Matlab, los parámetros adecuados para que el modelo lineal tenga un
comportamiento deseado.
2) Se refinaron estos controladores, matemáticamente obtenidos, a través de
simulaciones del modelo no lineal mediante Simulink.
3) Una vez obtenidos los controladores en tiempo continuo, se discretizaron y
volvieron a refinarse de nuevo en Simulink.
4) Como último paso se prueban en el sistema real y terminan de ajustarse.
82
7.3 MODELADO DEL SISTEMA DE CONTROL
Para el diseño del sistema de control se modelo el sistema completo.
Figura 35 Diagrama de alto nivel del sistema
Dicho modelo consta de tres bloques principales:
• Modelo de la aeronave
• Generación de referencias
• Controladores
83
7.3.1 MODELO DE LA AERONAVE
El modelo de aeronave modela las características dinámicas de UAV Viewer. Para el
diseño de este modelo se han usado los bloques proporcionados por Aerosim.
Figura 36 Modelo de la aeronave
En la siguiente figura podemos ver el contenido de este subsistema:
Figura 37 Detalle del modelo de la aeronave
El bloque Aerodinamics calcula los momentos y fuerzas aerodinámicos. Este bloque
pertenece al Aerosim toolset, y ha sido parametrizado según los coeficientes
dinámicos a partir de las derivadas d
El bloque Propulsión model
sistema de propulsión, compuesto por el motor eléctrico y la hélice.
calcula los momentos y fuerzas aerodinámicos. Este bloque
pertenece al Aerosim toolset, y ha sido parametrizado según los coeficientes
a partir de las derivadas de estabilidad del Viewer.
Figura 38 Modelo de cálculo aerodinámico
ropulsión model calcula la fuerza y el momento de empuje producido por el
sistema de propulsión, compuesto por el motor eléctrico y la hélice.
84
calcula los momentos y fuerzas aerodinámicos. Este bloque
pertenece al Aerosim toolset, y ha sido parametrizado según los coeficientes
calcula la fuerza y el momento de empuje producido por el
El bloque Aircraft Inertia recoge la matriz de inercia del avión. Esta matriz solo
depende la geometría del cuerpo.
El bloque Equations of Motion
las fuerzas y momentos a las variables especificadas en los puertos de salida que
aparecen a la derecha de la figura.
El bloque Earth es un modelo de la Tierra.
que afectan al avión es necesario tener en cuenta los cambios producidos en éstas por
el modelo de la Tierra. De esta forma y ya que la Tierra no es esférica sino que se
modela como un elipsoide, se tendrá que dependiendo de la posic
Figura 39 Modelo del sistema de propulsión
recoge la matriz de inercia del avión. Esta matriz solo
depende la geometría del cuerpo.
Equations of Motion implementa las ecuaciones que permiten tr
las fuerzas y momentos a las variables especificadas en los puertos de salida que
a la derecha de la figura.
Figura 40 Ecuaciones del movimiento
es un modelo de la Tierra. Para obtener una simulación de las variables
que afectan al avión es necesario tener en cuenta los cambios producidos en éstas por
el modelo de la Tierra. De esta forma y ya que la Tierra no es esférica sino que se
modela como un elipsoide, se tendrá que dependiendo de la posición en la cual se
85
recoge la matriz de inercia del avión. Esta matriz solo
implementa las ecuaciones que permiten transformar
las fuerzas y momentos a las variables especificadas en los puertos de salida que
ación de las variables
que afectan al avión es necesario tener en cuenta los cambios producidos en éstas por
el modelo de la Tierra. De esta forma y ya que la Tierra no es esférica sino que se
ión en la cual se
encuentre el avión se tendrá un determinado campo magnético, radio local, gravedad
y nivel del mar sobre el que medir la altitud.
Para calcular el campo magnético también se usará la posición del avión y el modelo
del campo magnético terrestre.
El bloque Atmosphere calcula una estimación de los parámetros del aire y calcula los
efectos del viento.
La atmósfera estándar vendrá representada por la presión estática, la temperatura,
densidad del aire y la velocidad del sonido, todo ello puede ser medido a partir de la
altitud sobre el nivel del mar.
Para el viento se aplicará una transformación desde el plano inercial al de ejes cuerpo,
se computan también las derivadas en el tie
se pueden capturar los efectos variantes con el tiempo del viento.
encuentre el avión se tendrá un determinado campo magnético, radio local, gravedad
y nivel del mar sobre el que medir la altitud.
Para calcular el campo magnético también se usará la posición del avión y el modelo
terrestre.
Figura 41 Modelo de la tierra
calcula una estimación de los parámetros del aire y calcula los
La atmósfera estándar vendrá representada por la presión estática, la temperatura,
densidad del aire y la velocidad del sonido, todo ello puede ser medido a partir de la
altitud sobre el nivel del mar.
Para el viento se aplicará una transformación desde el plano inercial al de ejes cuerpo,
se computan también las derivadas en el tiempo del vector velocidad y de esta manera
se pueden capturar los efectos variantes con el tiempo del viento.
86
encuentre el avión se tendrá un determinado campo magnético, radio local, gravedad
Para calcular el campo magnético también se usará la posición del avión y el modelo
calcula una estimación de los parámetros del aire y calcula los
La atmósfera estándar vendrá representada por la presión estática, la temperatura, la
densidad del aire y la velocidad del sonido, todo ello puede ser medido a partir de la
Para el viento se aplicará una transformación desde el plano inercial al de ejes cuerpo,
mpo del vector velocidad y de esta manera
Finalmente, indicar que todos los parámetro del modelo se cargan de el archivo
viewerconfig.mat el cual contiene
la hélice y el motor y la matriz de inercia de la aeronave, de esta forma podemos
modificar fácilmente los parámetros del modelo.
7.3.2 BLOQUE DE GENERACIÓN
Una de las partes más importantes de todo vehículo aéreo es la que corresponde a la
generación de las referencias que éste deberá seguir para conseguir alcanzar un
comportamiento determinado. Por ello, debe de existir un módulo que permita
traducir el plan a seguir del avión a las variables sobre las que los controladores de
bajo nivel actuarán para proporcionar en las superficies deflectoras del vehículo la
posición que permita llegar al objetivo.
7.3.2.1 ENVOLVENTE DE VUELO
La envolvente de vuelo la conforman el conjunto de actitudes críticas que un avión
nunca debería sobrepasar puesto que podría perderse el control de éste y acabar en
desastre. Generalmente en el diseño de esta envolvente se deja un margen entre el
rango máximo que no se debe superar y los valores críticos de las variables, de esta
forma si en algún momento se sobrepasaran, quedaría alguna posibilidad de llevar de
nuevo al avión a una actitud segura.
En el diseño del sistema de control de un vehículo aéreo no t
de tener en cuenta que al crear las referencias para alcanzar un objetivo determinado,
no deberían superarse las condiciones críticas del vehículo. Por ejemplo, deberá de
buscarse que esté siempre entre la velocidad máxima y mínim
Figura 42 Modelo de la atmosfera
Finalmente, indicar que todos los parámetro del modelo se cargan de el archivo
el cual contiene las características aerodinámicas, características de
la hélice y el motor y la matriz de inercia de la aeronave, de esta forma podemos
modificar fácilmente los parámetros del modelo.
BLOQUE DE GENERACIÓN DE REFERENCIAS (HIGHT LEVEL)
Una de las partes más importantes de todo vehículo aéreo es la que corresponde a la
generación de las referencias que éste deberá seguir para conseguir alcanzar un
comportamiento determinado. Por ello, debe de existir un módulo que permita
el plan a seguir del avión a las variables sobre las que los controladores de
bajo nivel actuarán para proporcionar en las superficies deflectoras del vehículo la
posición que permita llegar al objetivo.
ENVOLVENTE DE VUELO Y GENERACIÓN DE REFERENCIAS
envolvente de vuelo la conforman el conjunto de actitudes críticas que un avión
nunca debería sobrepasar puesto que podría perderse el control de éste y acabar en
desastre. Generalmente en el diseño de esta envolvente se deja un margen entre el
o que no se debe superar y los valores críticos de las variables, de esta
forma si en algún momento se sobrepasaran, quedaría alguna posibilidad de llevar de
nuevo al avión a una actitud segura.
En el diseño del sistema de control de un vehículo aéreo no tripulado (UAV), se habrá
de tener en cuenta que al crear las referencias para alcanzar un objetivo determinado,
no deberían superarse las condiciones críticas del vehículo. Por ejemplo, deberá de
buscarse que esté siempre entre la velocidad máxima y mínima, que los ángulos de
87
Finalmente, indicar que todos los parámetro del modelo se cargan de el archivo
las características aerodinámicas, características de
la hélice y el motor y la matriz de inercia de la aeronave, de esta forma podemos
Una de las partes más importantes de todo vehículo aéreo es la que corresponde a la
generación de las referencias que éste deberá seguir para conseguir alcanzar un
comportamiento determinado. Por ello, debe de existir un módulo que permita
el plan a seguir del avión a las variables sobre las que los controladores de
bajo nivel actuarán para proporcionar en las superficies deflectoras del vehículo la
envolvente de vuelo la conforman el conjunto de actitudes críticas que un avión
nunca debería sobrepasar puesto que podría perderse el control de éste y acabar en
desastre. Generalmente en el diseño de esta envolvente se deja un margen entre el
o que no se debe superar y los valores críticos de las variables, de esta
forma si en algún momento se sobrepasaran, quedaría alguna posibilidad de llevar de
ripulado (UAV), se habrá
de tener en cuenta que al crear las referencias para alcanzar un objetivo determinado,
no deberían superarse las condiciones críticas del vehículo. Por ejemplo, deberá de
a, que los ángulos de
viraje no sean excesivos, que el ángulo de pitch no sea tal que haga entrar en pérdida
al avión, etc.
En la ilustración aparecen las principales variables a tener en consideración para no
sobrepasar la envolvente de vuelo.
No sólo es importante respetar estos valores, sino que es conveniente que al generar
las referencias éstas no se generen de una manera brusca, un ejemplo de esto sería la
introducción de un escalón de gran am
a controlar. Esto se debe a que si introducimos un salto en la referencia, el servo lo
seguirá dando un cambio muy brusco en la superficie deflectora y por tanto haciendo
que las variables de estado cambien
un comportamiento indeseado que podría llegar a ser incontrolable.
Para evitar esto, en la generación de referencias se ha implantado un pequeño bloque
que se encargue de incrementar o decrementar la refere
otra parte se ocupa de que jamás se sobrepase la envolvente de vuelo.
En la figura se observa un ejemplo de cómo se ha implementado en Simulink este
bloque:
La ilustración muestra como se genera la referencia de altitud para los controladores
de bajo nivel a partir de la altura que se quiere alcanzar: Por una parte se tiene como
viraje no sean excesivos, que el ángulo de pitch no sea tal que haga entrar en pérdida
En la ilustración aparecen las principales variables a tener en consideración para no
sobrepasar la envolvente de vuelo.
Figura 43 Envolvente de vuelo
No sólo es importante respetar estos valores, sino que es conveniente que al generar
las referencias éstas no se generen de una manera brusca, un ejemplo de esto sería la
introducción de un escalón de gran amplitud en relación con la magnitud de la variable
a controlar. Esto se debe a que si introducimos un salto en la referencia, el servo lo
seguirá dando un cambio muy brusco en la superficie deflectora y por tanto haciendo
que las variables de estado cambien súbitamente, provocando oscilaciones y por tanto
un comportamiento indeseado que podría llegar a ser incontrolable.
Para evitar esto, en la generación de referencias se ha implantado un pequeño bloque
que se encargue de incrementar o decrementar la referencia de una forma lineal y por
otra parte se ocupa de que jamás se sobrepase la envolvente de vuelo.
En la figura se observa un ejemplo de cómo se ha implementado en Simulink este
Figura 44 Limitación de referencias
lustración muestra como se genera la referencia de altitud para los controladores
de bajo nivel a partir de la altura que se quiere alcanzar: Por una parte se tiene como
88
viraje no sean excesivos, que el ángulo de pitch no sea tal que haga entrar en pérdida
En la ilustración aparecen las principales variables a tener en consideración para no
No sólo es importante respetar estos valores, sino que es conveniente que al generar
las referencias éstas no se generen de una manera brusca, un ejemplo de esto sería la
plitud en relación con la magnitud de la variable
a controlar. Esto se debe a que si introducimos un salto en la referencia, el servo lo
seguirá dando un cambio muy brusco en la superficie deflectora y por tanto haciendo
súbitamente, provocando oscilaciones y por tanto
Para evitar esto, en la generación de referencias se ha implantado un pequeño bloque
ncia de una forma lineal y por
En la figura se observa un ejemplo de cómo se ha implementado en Simulink este
lustración muestra como se genera la referencia de altitud para los controladores
de bajo nivel a partir de la altura que se quiere alcanzar: Por una parte se tiene como
89
entradas la altitud que se quiere alcanzar y la altitud del UAV en ese momento, se
calcula la diferencia entre ambos y se satura a una diferencia máxima, la cual se suma
a la altitud actual. De esta manera cuando existan grandes escalones entre la posición
actual del avión y la deseada, la referencia a seguir por los controladores irá variando a
medida que el UAV vaya realizando la maniobra, de esta forma los errores con los que
trabajan los PIDS de los controladores, no serán excesivos y por lo tanto no provocarán
acciones bruscas en los servos que mueven las superficies de navegación. Por otra
parte, se puede observar también en la figura 4 como antes de entregar finalmente la
referencia deseada, ésta pasa por un saturador que será el encargado de que esta
referencia esté dentro de los límites permisibles dentro de la envolvente de vuelo.
Con este sencillo método se consigue que el avión quede siempre dentro de las
condiciones estables de vuelo y que se puedan alcanzar a las actitudes deseadas de
una forma suave.
7.3.2.2 MODO DE VUELO
En todo sistema de guiado es imprescindible que exista la oportunidad de seguir una
ruta determinada, en este caso la ruta será indicada mediante waypoints, los cuales
podrán estar dados por:
-Sistema NED: Está dado en metros y el origen de referencia es fijado en la superficie
de la tierra, preferiblemente en el lugar desde el que el UAV comienza el movimiento.
En él, el eje Y apunta al norte, el eje X apunta al este y el Z hacia abajo.
-Latitud, longitud y altitud.
El UAV mediante una ley de seguimiento de trayectorias, que será vista en el siguiente
apartado, tratará de alcanzar el siguiente waypoint. Se generarán referencias para que
los controladores de la dinámica lateral puedan hacer que el UAV alcance los puntos
deseados en el eje XY. A la vez el controlador longitudinal (elevador) tratará de
alcanzar la altitud especificada para dichos puntos. Por otra parte cabrá la posibilidad
de especificar la velocidad a la que se desea realizar esta ruta, el encargado de que
esto sea posible será el motor, por lo que es a éste al que le llegará la referencia de
velocidad.
En el modelo creado en Simulink llamado “High_Level.mdl” se encuentra el bloque que
permite configurar esta ruta y sus características y cuadro de diálogo se muestran en la
figura.
90
Figura 45 Configuración de waypoints y velocidad
En este caso se desea que cuando el UAV llegue al último punto de su ruta vuelva al
primero.
7.3.2.3 SEGUIMIENTO DE TRAYECTORIAS
En este apartado se explicará la ley que se ha implementado para generar un yaw rate
que permita llegar al siguiente waypoint. También se mostrará el módulo que
especifica cuando se ha alcanzado el objetivo y en qué momento se ha de ir al
siguiente.
LEY DE CONTROL
La ley que se ha implementado trata de llevar al UAV al siguiente Waypoint (Wp2) a lo
largo de la línea que une al Wp1 y el Wp2. La posición y velocidad del vehículo pueden
estar dadas, como se especificó anteriormente, tanto en un plano de referencia
<Norte, Este> como en coordenadas latitud y longitud. La nomenclatura utilizada será
la mostrada en la siguiente tabla.
91
Nomenclatura. Significado.
Xtrack Módulo de la distancia entre Wp1 y Wp2 (m).
Ytrack Distancia lateral a línea que une los waypoints(m).(Cross track)
X´track=∂Xtrack/∂t Velocidad en ejes track (m/s).
Y´track=∂Ytrack/∂t Velocidad Cross-track (m/s).
U Vector velocidad del UAV (m/s).
W Vector viento (m/s).
rCMD Yaw-rate requerido (rad/s).
),( NORTHYU∠=ψ Heading (rad).
),( NORTHw YW∠=ψ
Dirección del viento (rad).
),,( 2112 NORTHpp YWW ⟩⟨∠=ψ Heading de la línea de la trayectoria (rad).
Tabla 13 Variables para el cálculo de trayectorias
La matriz de rotación que permitirá transportar la posición del avión al sistema de ejes
<Xtrack,Ytrack> será la siguiente :
−−−−−
=)2/cos()2/sin(
)2/sin()2/cos(
1212
1212
πψπψπψπψ
ψT
Por lo tanto es posible obtener el siguiente resultado:
UTUtrack
rr
ψ= y WTWtrack
rr
ψ= de esta manera el modelo cinemático del UAV puede
ser expresado mediante las siguientes ecuaciones no lineales:
)cos())(cos( 1212 ψψψψ −+−= wtrack WtUX&
)sin())(sin( 1212 ψψψψ −−−−= wtrack WtUY&
)()( trt CMD=ψ&
La estrategia de control consistirá en apuntar el vector Velocidad (Ground Speed) en la
dirección de la línea que une los waypoints para interceptar a ésta en el punto C. Este
punto está determinado por el parámetro k, donde la distancia desde el Wp2 hasta el
punto C es en todo momento (1-k)Xtrack.
Esta estrategia está basada en el establecimiento de la posición y la velocidad
mediante la siguiente relación:
track
track
track
track
Y
Y
kX
X &&
= donde el error vendrá dado por tracktracktracktrack YkXYXe && ⋅−⋅= y debe
ser conducido a 0, para ello se genera un yaw rate proporcional a este error y se satura
92
a (+0.25, -0.25) rad/s ya que velocidades angulares mayores a este valor podrían ser
críticas para el UAV al comandar un giro demasiado rápido. Aparte se ha introducido
un filtro para contrarrestar la dinámica lenta del vehículo y tras éste se ha
transformado el yaw rate a una referencia en roll la cual será seguida por los
controladores de bajo nivel.
En el UAV implementado el parámetro K se ha puesto a 1 ya que es el que ofrece las
respuestas más suaves al no obligar al vehículo a alinearse con la línea de trayectoria
cortando esta en el punto especificado por C, sino que en todo momento lo que se
apuntará es al Waypoint destino y se tratará de pasar por él. Sin embargo sería
también muy factible el escoger otros valores para K, por ejemplo para distancias
largas podrían usarse K=0.5, por lo que se trataría de alcanzar un error lateral igual a 0
a mitad de camino y hace que el UAV siguiera la línea que une ambos waypoints.
Para la ganancia proporcional al error que genera el yaw rate ocurre lo siguiente: Las
ganancias para distancias cortas (del orden de 102m) han de ser mayores que las que
pertenecen a distancias más largas (orden 103 m), ya que si se usase la misma, al existir
errores grandes en Xtrack o Ytrack, se generaría un yaw rate tan grande que terminaría
por ser saturado y el avión comenzaría a dar vueltas. Por este motivo se ha utilizado
una ganancia dinámica, que dependerá del módulo de la distancia entre los waypoints
inicial y destino, de esta manera el UAV realizará la maniobra de una manera óptima
independientemente de la distancia que halla entre los puntos de su ruta.
BLOQUE DE GENERACIÓN DE TRAYECTORIA.
Para poder aplicar la ley de control expuesta en el anterior subapartado, existe un
módulo que indica en todo momento entre qué waypoints se encuentra el UAV,
cuándo debe girar y la ganancia que corresponde a dicho tramo.
Para ello se ha creado una función en Matlab denominada Track que podrá
encontrarse en el apéndice 1 de una forma íntegra para comprender de una forma
mejor cómo funciona. Aquí se esbozará un resumen de su funcionamiento.
1-Recibe el vector con la posición del UAV y todos los waypoints.
2-Calcula el error de posición y cuando éste es menor que una determinada ley (ésta
depende de la magnitud del giro a realizar para el siguiente waypoint y el Xtrack del
tramo actual) entonces comienza el giro. De esta manera se suavizan las trayectorias
realizadas por el UAV. Si se ha llegado al último waypoint se volverá al primero.
3-Calcula la constante proporcional que multiplicará al error dado por la ley de control.
4-Genera las salidas siguientes: Coordenadas de los waypoints entre los que se
encuentra el avión, altura a seguir en este tramo y la constante proporcional para el
yaw rate.
93
EJEMPLO DE SEGUIMIENTO DE RUTA.
A continuación se expondrá un ejemplo de cómo seguiría una ruta en la que se
alternan distancias largas y cortas entre waypoints para comprobar cómo
efectivamente la ley de control y el generador de trayectorias funcionan
correctamente.
Los Waypoints a seguir son:
Vector de Xe: [0, 400, 800, 2600, 2000, -3000,-1200]
Vector de Ye: [0, 0, 500, 700, 1500, 4000, 1000]
Vector de Alturas: [1000,1000, 1000, 1050, 1050, 1100, 1100]
En este ejemplo se comienza a una altura de 1000 metros desde el punto (0,0), a una
velocidad de 23 m/s (durante el trayecto el UAV irá a 24 m/s), y se ha decidido que gire
antes de llegar a los waypoints de tal manera que mientras mayor sea el giro a realizar
para el siguiente destino, antes se realizará dicho giro. Esta es una ley que podrá
cambiarse simplemente modificando las constantes del código para el cambio de
waypoints.
La ilustración muestra los waypoints y el recorrido del UAV.
Como es posible de observar el UAV sigue la ruta pasando por todos los waypoints
excepto el que se encuentra en (-3000, 4000), esto no es un error sino que al ser un
giro muy grande el UAV por la ley introducida para el cambio de waypoints comenzará
-4000 -3000 -2000 -1000 0 1000 2000 3000-500
0
500
1000
1500
2000
2500
3000
3500
4000
Xeste (m)
Yno
rte(
m)
94
su giro antes. Esto, como se ha expresado hace un momento, puede cambiarse e
incluso anularse.
A continuación se mostrará en las cómo se alcanzan las alturas y el cambio en la
constante que multiplicará al error para la generación del yaw rate deseado.
Figura 46 Altura
Figura 47 Ganancia dinámica
0 100 200 300 400 500 600 700 800980
1000
1020
1040
1060
1080
1100
1120
Tiempo (s)
Alti
tud(
m)
0 100 200 300 400 500 600 700 800-2.5
-2
-1.5
-1
-0.5
0x 10
-3
Tiempo (s)
Gan
anci
a (k
)
95
Como es posible observar, la altura se sigue perfectamente y la ganancia proporcional
es mayor en valor absoluto para distancias cortas que para las largas, lo que permite
seguir los waypoints de una manera correcta.
7.3.2.4 IMPLEMENTACIÓN EN SIMULINK
Figura 48 Modelo de alto nivel de generación de referencias
En el subsistema Modo 1 se generan y limitan las referencias de alto nivel (waypoints y
velocidad).
Todos los cálculos serán tratados por el módulo Guidance, que estará formado por:
• Bloque High level 1-4: en su interior se implementan las operaciones para
calcular las referencias de bajo nivel.
• Salidas: entrega al sistema de bajo nivel (control de actuadores) las referencias.
96
De estos bloques el que más elaboración conlleva es el que trata los modos de vuelo 1,
se ilustra en la siguiente figura:
Figura 49 Bloque Guidance
7.3.3 CONTROLADOR DE BAJO NIVEL
En el bloque Control System1 se implementan los controladores de bajo nivel para el
Viewer.
Figura 50 Controlador
Este es el módulo que implementaremos en el microcontrolador.
Las entradas de este subsistema son las siguientes:
• States: el controlador utiliza como entradas las medidas dinámicas del estado
de la aeronave. En un sistema inercial estas medidas las proporciona una
unidad de medida inercial y un GPS. Normalmente los datos generados por
estos sensores suelen procesarse median un filtro de Kalman que nos
proporcionará una estimación de la posición y actitud mejor que la que pueden
97
proporcionar ambos sensores por separado, especialmente si se utilizan
giróscopos y acelerómetro de baja precisión, como pueden ser los dispositivos
basados en sensores MEMS, que por su reducido tamaño y peso, son los únicos
que pueden montarse en un AUV de las dimensiones del Viewer.
• Lat Ref: referencias de latitud y longitud, si se utilizan ejes GWS, o metros en
los ejes X e Y si se utiliza un sistema de referencia local.
• Th Ref: referencia de velocidad.
• Elev ref: referencia de altitud.
Dentro del subsistema estas entradas se formatean para pasarlas a bloque AP/AT,
donde se implementan los controladores.
Figura 51 Modelo de alto nivel del controlador
El contenido del subsistema AP/AT se muestra en la siguiente figura:
Figura 52 Detalle del subsistema AP/AT
98
Como se puede observar, tenemos tres controladores de alto nivel:
Throttle: este controlador regual la potencia aplicada al motor para conseguir
alcanzar o mantener la referencia de velocidad de entrada.
Autopilot: este controlador regulla la altura de la aeronave. Se ha llamado autopilot
ya que clásicamente la única función de los autopilotos era la de mantener la
altitud.
Lateral: controla la dinámica lateral de la aeronave.
En los siguientes apartados veremos la implementación de cada uno de los
controladores.
7.3.3.1 SUBSISTEMA THROTTLE
Como se ha comentado anteriormente, este controlador actúa sobre el motor para
intentar mantener la referencia de velocidad proporcionada por el subsistema hight
level.
Figura 53 Subsistema Throttle
La salida de este subsistema está saturada para intentar mantener la aeronave dentro
de su envolvente de vuelo segura.
La implementación se ha hecho mediante un controlador PID:
99
Figura 54 Controlador de Throttle
Las entradas de este controlador son:
• Velocidad de referencia: proporcionada por el modulo higth level.
• Velocidad de la aeronave: proporcionada por el modelo de la aeronave.
7.3.3.2 SUBSISTEMA AUTOPILOT
Este controlador mantendrá la altitud de la aeronave según la referencia
proporcionada por el modulo higth level.
La salida de este sistema actuara sobre el elevador del avión.
Está compuesto por dos subsistemas:
• Altitude to pitch: generara un pitch para alcanzar la altura necesaria.
• Pitch hold Attitude & SAS: implementa un controlador para mantener el pitch y
un sistema de aumento de la estabilidad.
Figura 55 Subsistema Autopilot
100
La implementación del subsistema altitude to pitch es la siguiente:
Figura 56 Modelo de de Altitude to Pitch
El subsistema Pitch Hold Attitude & SAS está compuesto a su vez por dos subsistemas:
• Pitch attitude hold: encargado de mantener el pitch de referencia
• SAS: es un control proporcional de aumento de la estabilidad que básicamente
lo que hace es corregir la salida del elevador en función de la medida
instantánea de pitch rate para tratar de compensar pequeñas perturbaciones
en el pitch debidas a turbulencias.
Figura 57 Subsistema Pitch hold attitude & SAS
La implementación del controlador Pitch attitude hold es la siguiente:
101
Figura 58 Pitch attitude hold
El objetivo de este controlador será hacer llevar el pitch al valor de la referencia
tratando que la oscilación de la respuesta mínima, tratando que el error en régimen
permanente sea nulo o muy pequeño y que la respuesta sea rápida. Para ello,
partiendo del lugar de las raíces, se estudiaron los distintos controladores que se
podrían aplicar para que los polos dominantes se encuentren en un lugar que nos
interese.
7.3.3.3 SUBSISTEMA LATERAL
Este controlador es uno de los más importantes ya que permite mantener el UAV a un
determinado heading. Para realizarlo hay que tener en cuenta que el rudder debe de
estar coordinado con los alerones para realizar en todo momento una compensación
del giro. Una coordinación o compensación de giro se define como una aceleración
lateral del avión nula (aceleración inercial en el eje cuerpo Y igual a 0).
Figura 59 Subsistema Lateral
102
Como puede observarse, este subsistema está compuesto de dos controladores de
bajo nivel (Roll Autopilot & SAS y Yaw Autopilot), responsables del control de la
dinámica lateral del avión.
En un giro coordinado el avión mantendrá el pitch y roll con respecto al sistema de
coordenadas de referencia, pero su heading cambiará continuamente a una velocidad
constante, por lo que las derivadas del roll y el heading serán nulas.
El subsistema Roll Autopilot & SAS implementa un sistema de aumento de la
estabilidad, con el mismo propósito que los implementados en los otros controladores,
y el controlador Roll Attitude Hold, que controla la acción de los alerones para
establecer el roll proporcionado como referencia por el módulo Higth level.
Figura 60 Roll autopilot
La implementación del controlador Roll Attitude Hold es la siguiente:
Figura 61 Roll attitude hold
Para que los giros estén coordinados se realiza una realimentación al rudder de la
aceleración lateral para que sean cero.
103
Figura 62 Yaw autopilot
En cuanto a la realimentación de la aceleración lateral, se pretende que ésta sea 0 en
el menor tiempo posible, por ello una idea común en el control de este bucle es
realizar un PI o PID que aumente la velocidad del sistema sin llegar a inestabilizarlo y
permita un error en régimen permanente de 0.
Figura 63 Ay to rudder
7.4 VERIFICACIÓN DEL DISEÑO MEDIANTE PRUEBAS HARDWARE IN THE LOOP
(HIL)
Los sistemas de aviónica, especialmente los sistemas de navegación y control de vuelo
son unos de los sistemas más críticos en una aeronave, si cabe aún más en una
aeronave autónoma. Por ello, conseguir probar dichos sistemas en el entorno más
realista posible es un proceso fundamental.
Un elemento esencial para hacer simulación realista es integrar el hardware real
dentro del entorno de simulación, ya que la experiencia nos dice que no siempre un
resultado obtenido en el entorno de simulación se comporta de igual manera al
104
implementarlo en el hardware final, y/o al integrarlo con el resto de subsistemas. Esto
es debido a las complejas interacciones entre el hardware y el software, que no
siempre son consideradas por los entornos de simulación. Adicionalmente, en un
sistema complejo, como lo es el sistema de navegación de una aeronave, la
complejidad de estas interacciones se extiende por lo general a todos los subsistema
que cooperan en la aeronave.
Mediante las pruebas del sistema final integrado en el entorno de diseño y simulación
es posible realizar verificaciones de comportamiento en múltiples escenarios, de esta
forma es posible la identificación de más problemas potenciales que mediante la
aplicación de pruebas por separado al hardware y al software.
7.4.1 METODOLOGÍA EMPLEADA
Partimos de nuestro modelo de diseño, compuesto por tres subsistemas:
• Modulo de control: realiza la acción de control sobre la aeronave de
forma que esta permanezca dentro de su envolvente vuelo estable.
• Modulo de navegación: proporciona las referencias al módulo
autopiloto, básicamente, la ruta que debe seguir.
• Modelo de la aeronave: implementa el modelo dinámico de la
aeronave, siendo este modelo la planta del sistema de control.
El subsistema que se codificará será el módulo de control, que realiza la acción de
control sobre el avión. Es sistema está compuesto de varios subsistemas que realizan
la acción de control sobre las superficies de control que determinaran en definitiva la
actitud de la aeronave. Como se vio anteriormente, cada uno de estos subsistemas
está compuesto de uno o varios controladores.
Para la integración del sistema implementado en el hardware definitivo, se enviaran
desde Simulink los estados y las referencias requeridas por los controladores mediante
un puerto serie.
Así mismo, las salidas de los controladores se enviaran por el puerto serie a Simulink
donde se aplicarán al modelo del avión.
En la siguiente figura se muestra el modelo utilizado para la simulación HIL:
105
Figura 64 Modelo de pruebas HIL
En la siguiente ilustración se represente un esquema de la configuración para la
simulación HIL:
106
Figura 65 Diagrama comunicaciones con el microcontrolador
Adicionalmente, para obtener una visualización visual del comportamiento del
sistema, se utilizará el simulador de vuelo FlighGear, el cual se comandará por UDP
desde Simulink con un módulo disponible para tal propósito.
Como sabemos, Simulink no es un entorno de simulación en tiempo real. Sin embargo,
podemos hacer una buena aproximación bajo ciertas condiciones empleando el
modulo RTMatlab.
Este módulo básicamente lo que hace es controlar el tiempo de ejecución de la
simulación, de esta forma, si el cálculo el tiempo de simulación del sistema es más
rápido que el tiempo real, con este bloque podemos conseguir relentizarlo hasta
aproximarse a tiempo real.
Para la simulación HIL, utilizaremos el bloque de comunicaciones serie en modo
bloqueante, con un timeout bajo. De esta forma también conseguimos relentizar la
simulación hasta aproximarla a tiempo real.
107
7.5 IMPLEMENTACIÓN DEL CONTROLADOR EN UN MICROCONTROLADOR NXP
LPC2148 CON FREERTOS
7.5.1 ARQUITECTURA SOFTWARE
La aplicación se compone de los siguientes módulos:
• Proceso de control: ejecuta el algoritmo de control, enviando los resultados a
través del puerto serie.
• Proceso de comunicaciones con Simulink: este proceso se encarga del parseo
de los datos procedentes de Simulink, almacenándolos en la memoria
compartida.
• Memoria compartida: la comunicación de las referencias de control entre el
proceso de comunicaciones y el proceso de control se realiza a través de una
estructura compartida. El acceso a esta estructura está protegido mediante un
mutex.
• Driver UART: Este módulo abstrae el acceso al hardware de la UART,
proporcionando un buffer de entrada y salida adicional al presente en el
hardware.
La siguiente figura ilustra las relaciones entre los distintos módulos que componen la
aplicación:
Figura 66 Relación entre componentes software
108
Cada uno de los procesos utilizará distintos servicios del sistema operativo, para la
temporización de la ejecución y las comunicaciones entre procesos. La siguiente figura
esquematiza las dependencias de los procesos con la API de FreeRTOS:
Figura 67 Relación entre la API de FreeRTOS y los procesos
La estrategia de tiempo real seguida es de tipo best effort. El proceso de control se
ejecutará de forma determinista independientemente del proceso de comunicaciones
con Simulink, de esta forma se garantiza la salida de control dentro del deadline aún
cuando pueda ocurrir un error o un retraso en el proceso de comunicaciones con
simulik.
Así mismo, el driver de la UART proporciona funciones no bloqueantes tanto para la
transmisión como para la recepción por el puerto serie, limitándose el procesamiento
al contexto de las RTI de la UART utilizada.
109
7.5.2 IMPLEMENTACIÓN DE LOS CONTROLADORES
En los siguientes puntos veremos cómo se ha efectuado la implementación de los
controladores vistos anteriormente.
Todos los controladores se ejecutan dentro del proceso de control (vTaskControlador),
que llamará de forma secuencial a cada uno de ellos, enviando la salida mediante el
driver de la UART.
7.5.2.1 BUCLE PRINCIPAL DEL PROCESO DE CONTROL
A continuación se presenta el listado del bucle principal del proceso:
portTASK_FUNCTION( vTaskControlador , pvParameters ) { ( void ) pvParameters; int reduct=0; Get_Sem_est_control(&xEstadosSem); //obtenemos el semáforo para el acceso a memoria compartida while (1) //bucle infinito { vTaskDelay(10); //El controlador se ejecutara cada 10ms if (xSemaphoreTake( xEstadosSem,portMAX_DELAY)==pdTRUE) //Obtenemos acceso a memoria compartida { memcpy (&estados,&IN_est_control,sizeof (TEstado)); //Copiamos los datos a una variable local para no bloquear a otros procesos memcpy (&control,&IN_ref_control,sizeof (TRefs_Control)); xSemaphoreGive(xEstadosSem); //Liberamos la memoria compartida } Potencia(); //Procesamos el controlador de velocidad Elevador(); //Procesamos el controlador de altitud Alerones_Deriva(); //Procesamos el controlador de heading if (reduct==3) //Diezmamos la salida para no saturar a Simulink { reduct=0; SendControl(); //Enviamos la salida a la cola del driver de la UART } else { reduct++; } }
}
Listado 3 Bucle principal del proceso de control
Como puede observarse, el bucle principal se limita a controlar la temporización de la
ejecución y a llamar a cada una de las funciones en las que se implementan los
distintos controladores.
110
7.5.2.2 CONTROLADOR DE VELOCIDAD
En este controlador se implementa el subsistema throttle.
El modelo de este controlador es el siguiente:
Figura 68 Controlador de velocidad
Recordemos que esta salida estaba saturada para no violar la envolvente de vuelo:
Figura 69 Saturación del control de velocidad
La codificación de este controlador es directa, tal y como puede apreciarse en el
siguiente listado:
void Potencia () { float ferr; float r1,r2,r3; static float d1[2]; static float d2; ferr=control.troRef-estados.Vtas; SATURA(ferr,0.5) //Saturación simetrica a +-0.5 //Implementación del controlador
111
r1=PRM_ganancias.VelP1*ferr; r2=r1; r3=(d1[1]*PRM_ganancias.VelP3)+r2; OUT_control.throttle=(r3*PRM_ganancias.VelP4)+d2; d1[1]=d1[0]; d1[0]=ferr; d2=OUT_control.throttle; OUT_control.throttle=ferr; //Saturación de la salida if (OUT_control.throttle>1.0) { OUT_control.throttle=1.0; } else if (OUT_control.throttle<0.0) { OUT_control.throttle=0.0; }
}
Listado 4 Controlador de velocidad
7.5.2.3 CONTROLADOR DE ALTITUD
Este controlador implementa el subsistema Autopilot.
Este modelo está compuesto a su vez por dos subsistemas, Altitude to pitch y Pitch
hold Attitude.
Sus modelos son:
Figura 70 Altitude to pitch
112
Figura 71 Controlador de pitch
Recordemos que el subsistema Pitch hold Attitude tiene su salida saturada y que
implementa un sistema de aumento de la estabilidad:
Figura 72 Saturación del control de pitch
La codificación es la siguiente:
void Elevador () { float ferr; float r1,r2,r3; static float d1; static float d2; AlturaToPicth(); //Procesamos Altura to picht //Implementación de pitch hold attitude ferr = pitch-estados.pitch; r1=ferr*PRM_ganancias.AHK1; r2=(d1*PRM_ganancias.AHK2)+r1; r3=(r2*PRM_ganancias.AHK3)+d2; OUT_control.profundidad=r3-SASElevador(); //Procesamos SAS SATURA(OUT_control.profundidad,0.3) //Saturación de la salida
}
Listado 5 Control de altitud
void AlturaToPicth () { float ferr; float r1,r2,r3; static float d1[2]; static float d2;
113
ferr=control.altRef-estados.alt; //saturación SATURA(ferr,10) //Implementación de Altitude to pitch r1=PRM_ganancias.ATPK1*ferr; r2=(PRM_ganancias.ATPK3*d1[0])+r1; r3=(PRM_ganancias.ATPK4*d1[1])+r2; pitch=(PRM_ganancias.ATPK2*r3)+d2; d1[1]=d1[0]; d1[0]=ferr; d2=pitch; //saturación SATURA(pitch,0.2)
}
Listado 6 Generación de pitch de referencia
float SASElevador () { return PRM_ganancias.ESASK*estados.q;
}
Listado 7 Sistema de aumento de la estabilidad
7.5.2.4 CONTROLADOR DE HEADING
Este controlador implementa el sistema Lateral.
Este sistema está compuesto por dos controladores, ya que la dinámica lateral y
longitudinal deben estar coordinadas:
• Roll Autopilot: controla el alabeo del avión. Esta implementado en la función Alerones().
• Yaw Autopilot: controla la guiñada del avión. Está implementado en la función Deriva().
El modelo del controlador Roll Autopilot es el siguiente:
114
Figura 73 Controlador de roll y SAS de roll
La implementación del controlador Roll Attitude Hold es la siguiente:
Figura 74 Controlador de roll
La codificación de este controlador es la siguiente:
void Alerones () { float ferr; float r1,r2; static float d1; static float d2; //Implementación de Roll Attitude Hold ferr=control.latRef-estados.roll; r1=(ferr*PRM_ganancias.RAHK1)+(d1*PRM_ganancias.RAHK2); r2=(r1*PRM_ganancias.RAHK3)+d2; OUT_control.alerones=r2-SASAlerones(); SATURA(OUT_control.alerones,0.3)
}
float SASAlerones () { return estados.p*PRM_ganancias.ALSASK;
}
115
Listado 8 Implementación de controlador de roll
El modelo de sistema Yaw Autopilot es:
Figura 75 Controlador de yaw y SAS de yaw
Siendo el modelo del subsistema Ay to rudder el siguiente:
Figura 76 Controlador de yaw
En el siguiente listado se muestra la codificación del sistema:
void Deriva () { float ferr; float r1,r2,r3,r4; static float d1[2]; static float d2; ferr=0.0-estados.ayb; r1=ferr*PRM_ganancias.RUDK1; r2=r1+d1[0]*PRM_ganancias.RUDK3; r3=r2+d1[1]*PRM_ganancias.RUDK4; r4=r3*PRM_ganancias.RUDK2+d2; OUT_control.deriva=r4-SASDeriva(); SATURA(OUT_control.deriva,0.3)
116
d1[1]=d1[0]; d1[0]=ferr; d2=r4; } float SASDeriva () { return estados.r*PRM_ganancias.RUDSASK;
}
Figura 77 Implementación del controlador de yaw
7.5.3 DRIVER UART
Para abstraer el hardware de las UARTs y simplificar su manejo, se ha implementado
un driver que se encarga de la gestión de las UARTs y la transmisión y recepción
asíncrona.
Se ha implementado una API que permite la configuración de las UART, proporciona
funciones de transmisión y recepción asíncrona, y acceso mediante colas de mensajes.
La implementación está dividida en dos partes principales, las funciones de
configuración, y las rutinas de tratamiento de interrupción.
El funcionamiento se basa en la utilización de colas de mensajes tanto para la
transmisión como para la recepción. Empleando las funciones de la API del driver, o
directamente con la API de FreeRTOS podemos acceder a estas colas de mensajes, lo
que permite la operación asíncrona y el uso de timeouts.
A continuación se lista el archivo uart.h, en el que está definida la API del driver:
#ifndef _UART_H_ #define _UART_H_ #include "FreeRTOS.h" #include "queue.h" // Tipo manejador de UART typedef void *xComPortHandle; /* * uartInit * Inicializa una de las UARTs * \param pxPort UART que se va a configurar * \param ulWantedBaud baudrate de las comunicaciones * \param uxQueueLength tamaño de las colas de tx y rx */ xComPortHandle uartInit (portCHAR pxPort, unsigned portLONG ulWantedBaud, unsigned portBASE_TYPE uxQueueLength); /* * uartPutString * Es un envoltorio de la cola de trasnmsión * Internamente llama a uartPutChar
117
* \param pxPort UART * \param pcString cadena a transmitir * \param xBlockTime tiempo de bloqueo o timeout */ void uartPutString (portCHAR pxPort, const signed portCHAR * const pcString, portTickType xBlockTime); /* * uartGetChar * * Esta función es un envoltorio para el acceso a la cola de recepción * \param pxPort UART * \param pcRxedChar referencia a buffer de recepción * \param xBlockTime tiempo de bloqueo o timeout */ signed portBASE_TYPE uartGetChar (portCHAR pxPort, signed portCHAR *pcRxedChar, portTickType xBlockTime); /* * uartPutChar * Es un envoltorio de la cola de trasnmsión * Internamente llama a uartPutChar * \param pxPort UART * \param cOutChar caracter * \param xBlockTime tiempo de bloqueo o timeout */ signed portBASE_TYPE uartPutChar (portCHAR pxPort, signed portCHAR cOutChar, portTickType xBlockTime); //void uartClose (portCHAR xPort); //Proporciona una referencia a la cola de mensajes de recepción de la UART 0 void uart0GetRxQueue (xQueueHandle *qh); //Proporciona una referencia a la cola de mensajes de recepción de la UART 0 void uart1GetRxQueue (xQueueHandle *qh); #endif
Listado 9 API del driver de la UART
El código completo se encuentra en el DVD adjunto.
7.5.4 COMUNICACIONES CON SIMULINK
Las comunicaciones con Simulink se efectúan mediante el driver de la UART.
La transmisión se hace directamente desde el proceso de control. El protocolo que se
ha definido es el siguiente:
118
1 2 3 a 6 7 a 10 11 a 14 15 a 18 19
A A elevador alerones deriva potencia /r
Tabla 14 Protocolo de transmision a Simulink
Para la recepción del estado y las referencias procedentes de Simulink, se hace
necesaria la implementación de una tarea independiente. Esta tarea está
implementada en el archivo hil.c.
El proceso se encarga de parsear los bytes recibidos y comprobar la integridad de los
paquetes. El protocolo es muy sencillo, limitándose a la transmisión de los valores, por
lo que la sincronización se hace mediante un timeout que comprueba el tiempo entre
paquetes. Si por alguna causa la recepción se desincronizase, al producirse el timeout
se descarta el paquete parcialmente recibido y se comenzaría la recepción a partir del
siguiente.
Este proceso, como se ha comentado anteriormente, parsea los datos recibidos,
almacenándolos en una estructura en memoria compartida a la que accederá el
proceso de control. Para evitar el acceso a datos incompletos, el acceso a esta
estructura está protegido mediante un mutex.
7.5.5 CONFIGURACIÓN DE FREERTOS
La configuración de FreeRTOS se ha hecho a partir de una configuración preexistente,
disponible en la demo que acompaña a FreeRTOS, concretamente la demo para el
LPC2106.
Se ha modificado la configuración para adaptarla a esta aplicación.
El siguiente listado muestra la configuración empleada:
#define configUSE_PREEMPTION 1 #define configUSE_IDLE_HOOK 0 #define configUSE_TICK_HOOK 0 #define configUSE_CO_ROUTINES 0 #define configCPU_CLOCK_HZ ( ( unsigned portLONG ) 60000000) #define configTICK_RATE_HZ ( ( portTickType ) 1000) #define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 10) #define configMINIMAL_STACK_SIZE ( ( unsigned portSHORT )256) #define configTOTAL_HEAP_SIZE ( ( size_t ) ( 20 * 1024 )) #define configMAX_TASK_NAME_LEN ( 20 ) #define configUSE_TRACE_FACILITY 0 #define configUSE_16_BIT_TICKS 0 #define configIDLE_SHOULD_YIELD 1 #define configUSE_MUTEXES 1 /* Co-routine definitions. */ #define configUSE_CO_ROUTINES 0 #define configMAX_CO_ROUTINE_PRIORITIES ( 10 )
119
/* 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 1 #define INCLUDE_vTaskSuspend 1 #define INCLUDE_vTaskDelayUntil 1 #define INCLUDE_vTaskDelay 1 #define INCLUDE_xTaskGetCurrentTaskHandle 1
#endif /* FREERTOS_CONFIG_H */
Listado 10 Configuración de FreeRTOS
Como puede observarse se ha configurado un tick rate de 1KHz, eso nos permite una
resolución de 1ms en las funciones de temporización de FreeRTOS.
También es de destacar que solo se ha configurado la planificación como expropiativa.
Al adaptar este archivo de configuración ha habido que indicar la frecuencia de reloj
del LPC2148, esto es importante porque FreeRTOS usa este parámetro para la
configuración del Timer.
También se han seleccionados los servicios de la API que se usan en la aplicación.
7.5.6 ESTRUCTURA DEL CÓDIGO FUENTE
La estructura del proyecto es muy similar al proyecto básico que se presentó en el
capítulo anterior. En la siguiente captura puede observarse el árbol que compone el
proyecto:
120
Figura 78 Archivos del proyecto Autopiloto
Pasamos a describir brevemente los archivos principales que componen la aplicación.
MAIN.C
Es el punto de entrada de la aplicación. En él se implementa la función main, en la que
se inicializa el hardware, se configura el driver de la UART, se crean los procesos y se
inicia la ejecución del planificador.
AUTOPILOTO.H/AUTOPILOTO.C
En estos archivos se definen las estructuras de datos usadas por el controlador, así
como la estructura de memoria compartida y las estructuras para el almacenamiento
de las ganancias de los controladores. Proporciona funciones para acceder al mutex de
acceso a memoria compartida y una función de inicialización de las ganancias.
HIL.C/HIL.C
En estos archivos se implementa la tarea encargada de la recepción de datos de
Simulink. Esta tarea es responsable del parseo de los datos y su escritura en memoria
compartida. La recepción se hace mediante el driver de la UART.
121
CONTROLADOR.H/CONTROLADOR.C
En estos archivos se implementa la tarea de control. Esta tarea ejecuta los distintos
controladores sobre los datos contenidos en memoria compartida. Tras el cómputo de
los controladores, el resultado se envía a Simulink empleando el driver de la UART.
UART.H/UART.C
En estos archivos se implementa la API del driver de las UARTs. Proporcionan
funciones de inicialización del driver, funciones de lectura y escritura, y referencias
para el acceso directo a las colas de mensajes de transmisión y recepción.
La función de inicialización crea las colas de mensajes, configura el hardware según los
parámetros indicados por el usuario y configura el VIC.
UARTISR.H/UARTISR.C
En estos archivos se implementan las rutinas de interrupción de la UART. Forman parte
del driver de la UART y se encargan de realizar las operaciones de transmisión y
recepción a bajo nivel. Para ello emplean las colas de mensajes creadas en la función
de inicialización.
FREERTOSCONFIG.H
Es el archivo de configuración de FreeRTOS, en el se configura el comportamiento del
SO así como los servicios disponibles.
Directorio lpc2148
Dentro de este directorio existen diversas librerías, con definiciones de los registros y
funciones de inicialización del microcontrolador. Estas librerías proceden de los
ejemplos que acompañan a FreeRTOS.
7.6 RESULTADOS OBTENIDOS
En este punto compararemos los resultados de la simulación en Simulink con la prueba
HIL. El objetivo de este análisis es validar la implementación en el hardware real
mediante comparación directa de los resultados.
Para realizar este análisis se establecerá la siguiente ruta de waypoints a seguir por la
aeronave:
122
A B C D E F
X 0 1000 1400 1000 400 -200 Y 0 0 600 1000 800 400 Z 1200 1300 1400 1300 1205 1400
COMPARACIÓN DE TRAYECTORIAS EN EL PLANO XY
En las siguientes figuras se muestran las trayectorias seguidas en el plano horizontal
tanto en la simulación en Simulink, como en la prueba HIL.
Simulink:
Figura 79 Trayectoria seguida en Simulink
Simulación HIL:
Figura 80 Trayectoria seguida durante la prueba HIL
123
Se puede apreciar como el error en trayectoria realizada con el hardware real es
despreciable. Este error viene dado principalmente por el hecho de usar aritmética de
punto flotante de 32bits, en lugar de los 64bit que emplea Simulink.
COMPARACIÓN DE TRAYECTORIAS EN EL EJE Z
Simulink:
Figura 81 Altura del UAV en la simulación con Simulink
Simulación HIL:
Figura 82 Altura del UAV durante la prueba HIL
124
En estas gráficas también se observa que las trayectorias son prácticamente
coincidentes.
Con estos resultados podemos afirmar que la respuesta de la implementación en el
microcontrolador LPC2148 con FreeRTOS es válida, cumpliendo los requisitos
funcionales de más alto nivel al ser su respuesta muy próxima a la simulación.
En un entorno de producción real, este hardware ya sería integrable en un UAV. A este
proceso le seguiría un proceso de refinamiento de los controladores, ya que con toda
seguridad, la respuesta del avión real no se ajuste completamente al modelo
empleado para el diseño del sistema de control.
125
8 CONCLUSIÓN
Tras el estudio de la familia, las herramientas y recursos disponibles, y la
implementación de un sistema de control con las mismas, hemos comprobado cómo
es viable el uso de herramientas libres para configurar un entorno de desarrollo fiable
y de alta calidad y prestaciones. Hemos verificado la versatilidad de la arquitectura y la
gran cantidad de recursos libres disponibles.
Este conjunto de características, hacen de esta familia una buena plataforma docente,
ya que además de ser una arquitectura ampliamente implantada y en continua
evolución, disponemos de todas las herramientas necesarias de forma gratuita, y en el
caso del hardware, a muy bajo coste.
Por otra parte se ha verificado la capacidad computacional de la misma, obteniendo
resultados satisfactorios en la implementación de un sistema de control en tiempo
real, cuya validez se ha probado mediante la realización de una prueba de tipo
hardware in the loop. Adicionalmente se ha demostrado la utilidad de este tipo de
pruebas, ya que permiten la verificación de un diseño de forma sencilla y fiable, ya que
se centra en la comprobación de requisitos funcionales de alto nivel.
126
127
9 LÍNEAS FUTURAS
Como desarrollo adicional de este proyecto se propone el estudio de la integración de
código generado automáticamente desde Simulink con la herramienta Realtime
Workshop. La integración de código generado mediante herramientas de diseño
basado en modelos puede presentar ventajas como la eliminación de errores de
codificación y permitir que se puedan hacer modificaciones en los modelos sin que ello
suponga una carga de trabajo adicional de codificación.
También resulta interesante el estudio de las familias Cortex-M3 y Cortex-R4,
especialmente indicadas para sistemas en tiempo real. Un desarrollo adicional podría
ser la implementación de un port de FreeRTOS para Cortex-R4, ya que todavía está
disponible.
Con respecto a la pruebas HIL, resulta interesante investigar este campo,
especialmente si se realizan con hardware especifico para tal propósito, como los
equipos PXI para LabView Realtime. Esto equipos permiten la realización de estas
pruebas en un verdadero entorno en tiempo real, contando con tarjetas de E/S
mediante las cuales se podría interfasear el sistema de control a más bajo nivel, por
ejemplo, se podría conectar la salida PWM de un controlador de servos directamente
al equipo PXI, este realizaría la decodificación de esta señal PWM y la aplicaría a la
modelo del sistema bajo control. De esta forma las pruebas HIL permiten probar no
solo la funcionalidad en cuanto a cálculo, sino también la correcta implementación de
los protocolos de E/S del sistema.
128
129
BIBLIOGRAFÍA
ARM7TDMI Technical Reference Manual , ARM Limited
The insider’s guide to the Philips ARM7 based microcontrollers, Trevor Martin, Hitex
Ltd., ISBM: 0-9549988 1
Using Open Source Tools for AT91SAM7S Cross Development, James P. Lynch
LPC214x User Manual, Koninklijke Philips Electronics
FreeRTOS reference manual, Richard Barry, Real Time Engineers Ltd.
Using the FreeRTOS Real Time Kernel – A Practical Guide, Richard Barry, Real Time
Engineers Ltd.
130
131
REFERENCIAS WEB
www.nxp.com/
http://www.arm.com/
http://www.freertos.org/
http://www.embeddedrelated.com/groups/lpc2000/1.php
http://openocd.berlios.de/web/
http://www.eclipse.org/
http://www.highintegritysystems.com/
http://www.mathworks.com/matlabcentral/
http://forum.sparkfun.com/
132
133
ANEXO A: FAMILIAS SOPORTADAS POR FREERTOS
Altera: Nios II
Atmel: CortexM3, ARM7, ARM9, AVR
Cortus: APS 3
Energy Micro: EFM32, Cortex M3
Freescale: HCS12, Coldfire, PowerPC
Fujitsu: MB91460, MB96340
Luminary Micro (adquirida por TI): Cortex M3
Microchip: PIC32, PIC24, dsPIC, PIC18
NEC: V850ES, 78K0R
NXP: Cortex M3, ARM7
Renesas: SuperH, H8S
Silicon Labs: 8051
ST: Cortex M3, ARM7, ARM9
TI: MSP430
Xilinx: Microblaze, PowerPC
Intel/AMD/Otros: x86
134
135
ANEXO B: CÓDIGO PARA EL CÁLCULO DE REFERENCIAS DE TRAYECTORIAS
function k = track(u) global I_ANT global J_ANT %Sacar los valores de la entrada. long = (length(u)-4)/3; x_camino = u(1:long); y_camino = u(long+1:2*long); h_camino = u(2*long+1:3*long); x_v = u(3*long+1); y_v = u(3*long+2); reset=u(3*long+3); tipo=u(3*long+4); %Valores de los indices correspondientes al camino. i=I_ANT; j=J_ANT; %Calculamos variables. x_dif=x_camino(i)-x_camino(j); y_dif=y_camino(i)-y_camino(j); ang=atan2(x_dif,y_dif); modulo=sqrt(((x_camino(i)-x_camino(j))^2)+((y_camin o(i)-y_camino(j))^2)); x_track=-(x_v*(cos(ang-pi/2))-(y_v*(sin(ang-pi/2))))+(x_camino(j)*(cos(ang-pi/2)))-(y_camino(j) *(sin(ang-pi/2)))+modulo; %Calculo el ángulo siguiente. m=i+1; if (m==long+1) m=1; end xd2=x_camino(m)-x_camino(i); yd2=y_camino(m)-y_camino(i); angsig=atan2(xd2,yd2); %Calculo la magnitud del giro siguiente. angtot=abs(angsig-ang); if (angtot>pi) angtot=(2*pi)-angtot; end %Selección de ganancias if (tipo==1) k=-(500/modulo)*0.002; else k=-(500/modulo)*0.002e7; end %Calculamos cuándo se realizará el giro error=(angtot*3)/pi;
136
error2=modulo*error/100; %logica de guiado. if (x_track<error2) j=i; i=i+1; if i==long+1 j=long; i=1; end end if (reset==1) i=2; j=1; end %Salidas. k=[x_camino(j),y_camino(j),x_camino(i),y_camino(i), k,h_camino(i)]; I_ANT=i; J_ANT=j;
137