Herramientas libres para la implementación de sistemas de control en tiempo real con microcontroladores ARM71

November 24, 2017 | Author: Sonia Nievas Garcia | Category: Arm Architecture, Central Processing Unit, Instruction Set, Microcontroller, Bit
Share Embed Donate


Short Description

Download Herramientas libres para la implementación de sistemas de control en tiempo real con microcontroladores ARM71...

Description

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍ A DE TELECOMUNICACIÓN UNIVERSIDAD DE MÁLAG A

PROYECTO FIN DE CARRERA

HERRAMIENTAS LIBRES PARA LA IMPLEMENTACIÓN DE SISTEMAS DE CONTROL EN TIEMPO REAL CON MICROCONTROLADORES ARM7

INGENIERÍA TÉCNICA DE TELECOMUNICACIÓN SISTEMAS ELECTRÓNICOS

MÁLAGA, 2010

ANTONIO JIMENEZ BELLIDO

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍ A DE TELECOMUNICACIÓN UNIVERSIDAD DE MÁLAG 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.: _________________

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍ A DE TELECOMUNICACIÓN UNIVERSIDAD DE MÁLAG A

HERRAMIENTAS LIBRES PARA LA IMPLEMENTACIÓN DE SISTEMAS DE CONTROL EN TIEMPO REAL CON MICROCONTROLADORES ARM7

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 de control, Hardware in the loop, Sistemas en tiempo real, FreeRTOS.

RESUMEN: En este proyecto se estudia el conjunto de herramientas libres disponibles para el desarrollo de aplicaciones de control 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. Adicionalmente 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 the loop.

Málaga, Septiembre de 2010

CONTENIDO

Contenido .......................................................................................................................... I Tabla de acrónimos ........................................................................................................ VII 1

Introducción ............................................................................................................. 1 1.1

Estado del arte y tendencias .............................................................................. 2

1.1.1

2

1.2

Objetivos del proyecto ....................................................................................... 4

1.3

Organización de la memoria .............................................................................. 4

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 2.8

3

ARM ............................................................................................................ 2

Interrupciones software ........................................................................... 14

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

Microcontrolador NXP LPC2148 ............................................................................. 21

I

4

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

Entorno y herramientas de desarrollo ................................................................... 37 4.1

Introducción ..................................................................................................... 37

4.2

El entorno de desarrollo .................................................................................. 38

4.2.1 4.3

Ubuntu Linux ............................................................................................ 38

Herramientas de desarrollo ............................................................................. 38

4.3.1

CodeSourcery G++ Lite ............................................................................. 38

4.3.2

Eclipse IDE ................................................................................................. 39

4.3.3

OpenOCD .................................................................................................. 39 II

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 5

Conclusiones .................................................................................................... 47

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 6

Aplicaciones de tiempo real ..................................................................... 51

Free RTOS ............................................................................................................... 55 6.1

Introducción a FreeRTOS. ................................................................................ 55

6.1.1 6.2

Multiprocesamiento en sistemas embebidos pequeños. ........................ 55

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 6.7

Abstracción de hardware mediante drivers. ............................................ 67

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 III

6.9 7

Conclusiones .................................................................................................... 75

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

IV

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

V

VI

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. VII

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.

VIII

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 1

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.corporateir.net/media_files/IROL/19/197211/ARM_Annual_Report_2009.pdf 2

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: •



3

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.

Hasta cuatro núcleos. 3



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.corporateir.net/media_files/IROL/19/197211/ARM_Annual_Report_2009.pdf 4

• •

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.

5

6

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 7

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.

8

Modo Modo 1 ARM THUMB CARGA

PC

2

PC

-

DECODIFICACIÓN PC-4

PC-2

-

-

PC-8

PC-4

-

-

EJECUCIÓN

3

4

5

6

-

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) 9

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 N Z C V

8 7 6 5 4 3 2 1 0 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 10

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 R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15(PC)

FIQ

Supervisor

Abort

IRQ

Undefined

R0 R1 R2 R3 R4 R5 R6 R7_fiq R8_fiq R9_fiq R10_fiq R11_fiq R12_fiq R13_fiq R14_fiq R15(PC)

R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13_svc R14_svc R15(PC)

R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13_abt R14_abt R15(PC)

R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13_irq R14_irq R15(PC)

R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13_und R14_und R15(PC)

CPSR

CPSR SPSR_fic

CPSR SPSR_svc

CPSR SPSR_abt

CPSR SPSR_irq

CPSR SPSR_und

Tabla 2 Bancos de registros

11

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. 12

Las siguientes tablas muestran los vectores asociados a cada modo de operación y el orden de prioridad de las excepciones. Excepción Reset Instrucción no definida Interrupción software (SWI) Aborto de precarga Aborto de datos IRQ(interrupción) FIQ(interrupción rápida)

Modo Supervisor Undefined Supervisor Abort Abort IRQ FIQ

Dirección del vector 0x00000000 0x00000004 0x00000008 0x0000000C 0x00000010 0x00000018 0x0000001C

Tabla 3 Vectores de interrupción

Prioridad 1 (La más alta) 2 3 4 5 6 (La menor)

Excepción Reset Data abort FIQ IRQ Prefetch abort 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. 13

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 Condición

28 1111

27 Valor

24

23

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.

14

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 EQ NE PL MI HI CS CC LS GE LT GT LE VS VC AL

Flags comparados Z=1 Z=0 N=0 N=1 C=1yZ=0 C=1 C=0 C=0yZ=1 N=V N != V Z=0yN=V Z = 1 y N!=V V=1 V=0 Todos ignorados

Significado Igual Distinto Positivo o cero Negativo Mayor (sin signo) Mayor o Igual (sin signo) Menor (sin signo) Menor o Igual (sin signo) Mayor o igual Menor Mayor Menor o igual Overflow No overflow 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 BL BX BLX

Salto Salto con enlace Salto con cambio 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. 15

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 EOR SUB RSB ADD ADC SBC RSC TST TEQ CMP CMN ORR MOV BIC MVN

AND lógico XOR lógico Resta Resta inversa Suma Suma con acarreo Resta con acarreo Resta inversa con acarreo Test Comprueba igualdad Comparación Comparación inversa OR lógico Mover Limpiar bit 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

COND

OP

Flag para habilitar los códigos de condición S

Operandos

Desplazamiento

R1,R2,R3

xx

Tabla 9 Formato de las instrucciones de procesado de datos

16

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 MULA UMULL UMLAL SMULL SMLAL

Multiplicación, operandos de 16 bit Multiplicación y acumulación, operandos de 16 bit Multiplicación sin signo, operandos de 32 bit Multiplicación y acumulación sin signo, operandos de 32 bit Multiplicación con signo, operandos de 32 bit 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 LDRH LDRSH LDRB LDRSB STR STRH SRHSH STRB STRSB

Load Word Load half Word Load signed half Word Load byte Load signed byte Store Word Store half Word Store signed half Word Store byte Store signed half byte

Tabla 11 Instrucciones de transferencia de datos

17

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

18

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.

19

20

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 21

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:

22

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

23

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

24

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. 25

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). 26

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.

27

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.

28

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).

29

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.

30

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 31

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.

32

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.

33

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.

34

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.

35

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.

36

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

37

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. 38

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 39

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

40

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.

41

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. 42

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 43

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

44

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.

45

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

46

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.

47

48

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.

49

• •

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. 50

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:

51

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

52

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.

53

54

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

12

Precertificado IEC61508 SIL3, FDA510(k) Class III y EN62304, cualificable para DO178B. 55

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.

56



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.

57

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 58

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.

59

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. 60

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.

61

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 62

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. 63

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. 64

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.

65

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;

66

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.

67



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.

68

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.

69

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

70

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:

71

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 72

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.

73

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).

74

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.

75

76

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.

77

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 hacer 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. Podemos Podemos observar un generador de referencias, éste es el encargado de indicar 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. dese

Figura 33 Diagrama de control de una aeronave

Los controladores se han diseñado específicamente para el UAV Viewer. Viewer Se trata de un sistema istema aéreo de supervisión robusto, ligero y de fácil transporte, diseñado para labores de Inteligencia, Observación Observa 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

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 79

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.

80

-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.

81

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

82

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

83

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 de d estabilidad del Viewer.

Figura 38 Modelo de cálculo aerodinámico

El bloque Propulsión 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

Figura 39 Modelo del sistema de propulsión

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 implementa las ecuaciones que permiten transformar tr las fuerzas y momentos a las variables especificadas en los puertos de salida que aparecen a la derecha de la figura.

Figura 40 Ecuaciones del movimiento

El bloque Earth es un modelo de la Tierra. Para obtener una simulación 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 modela como un elipsoide, se tendrá que dependiendo de la posición posición en la cual se 85

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.

Figura 41 Modelo de la tierra

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, la 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 tiempo del vector velocidad y de esta manera se pueden capturar los efectos variantes con el tiempo del viento.

86

Figura 42 Modelo de la atmosfera

Finalmente, indicar que todos los parámetro del modelo se cargan de el archivo viewerconfig.mat 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.

7.3.2

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 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 Y GENERACIÓN DE REFERENCIAS

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 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 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, mínima, que los ángulos de 87

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.

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 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 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 bloque:

Figura 44 Limitación de referencias

lustración muestra como se genera la referencia de altitud para los controladores La ilustración de bajo nivel a partir de la altura que se quiere alcanzar: Por una parte se tiene como 88

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.

89

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 como en coordenadas latitud y longitud. La nomenclatura utilizada será la mostrada en la siguiente tabla.

90

Nomenclatura. Xtrack Ytrack X´track=∂Xtrack/∂t Y´track=∂Ytrack/∂t U W rCMD

ψ = ∠(U,YNORTH)

Significado. Módulo de la distancia entre Wp1 y Wp2 (m). Distancia lateral a línea que une los waypoints(m).(Cross track) Velocidad en ejes track (m/s). Velocidad Cross-track (m/s). Vector velocidad del UAV (m/s). Vector viento (m/s). Yaw-rate requerido (rad/s). Heading (rad).

ψ w = ∠(W ,YNORTH)

Dirección del viento (rad).

ψ 12 = ∠(〈Wp1 ,Wp 2 〉, YNORTH )

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 será la siguiente :  cos(ψ 12 − π / 2) − sin(ψ 12 − π / 2)   Tψ =   sin(ψ 12 − π / 2) cos(ψ 12 − π / 2) 

Por lo tanto es posible obtener el siguiente resultado:

r r r r Utrack = TψU y Wtrack = TψW de esta manera el modelo cinemático del UAV puede ser expresado mediante las siguientes ecuaciones no lineales:

X& track = U cos(ψ (t ) −ψ 12 ) + W cos(ψ w −ψ 12 ) Y&track = −U sin(ψ (t ) −ψ 12 ) −W sin(ψ w −ψ 12 )

ψ& (t) = rCMD(t) 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: X& track Y&track = donde el error vendrá dado por e = X& track ⋅ Ytrack − kX track ⋅ Y&track y debe kX track Ytrack ser conducido a 0, para ello se genera un yaw rate proporcional a este error y se satura 91

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. 92

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.

4000

3500

3000

Ynorte(m)

2500

2000

1500

1000

500

0

-500 -4000

-3000

-2000

-1000 Xeste (m)

0

1000

2000

3000

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á 93

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.

1120

1100

1080

1040

1020

1000

980

0

100

200

300

400 Tiempo (s)

500

600

700

800

Figura 46 Altura

-3

0

x 10

-0.5

-1 Ganancia (k)

Altitud(m)

1060

-1.5

-2

-2.5

0

100

200

300

400 Tiempo (s)

500

600

700

800

Figura 47 Ganancia dinámica

94

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. 95

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 96

• • •

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

97

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:

98

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

99

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:

100

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

101

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.

102

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 103

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:

104

Figura 64 Modelo de pruebas HIL

En la siguiente ilustración se represente un esquema de la configuración para la simulación HIL:

105

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.

106

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

107

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. 108

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.

109

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

110

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.throttlepi) 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;

135

error2=modulo*error/100; %logica de guiado. if (x_track
View more...

Comments

Copyright ©2017 KUPDF Inc.
SUPPORT KUPDF