Sei sulla pagina 1di 13

GUÍA DE ESTUDIO

(V1)

Eduardo Javier Pérez Rodríguez


(edu@uma.es)
Mayo 2020
Microcontroladores – Grado en Sistemas de Telecomunicación – Curso 2019/2020 Tema 8: Arquitectura

T8.0
En este tema se va a realizar una breve descripción de la arquitectura del microcontrolador, tratando aspectos
importantes necesarios para su operación. Es importante notar que se trata de un tema introductorio, y que en
ningún momento se pretende realizar una detallada descripción de la arquitectura del microcontrolador, que
requeriría una extensión mucho mayor de la realizada.

T8.1
El tema se divide en cinco puntos:
1. Una presentación del mapa de memoria del sistema.
2. Un análisis de la organización de la memoria.
3. Una descripción de los aspectos más importantes de la CPU.
4. Un análisis del mecanismo de reset.
5. Una descripción detallada del tratamiento de las interrupciones.

T8.2
Comenzamos con la presentación mapa de memoria.

T8.3
Un microcontrolador es un sistema formado por tres bloques interconectados entre sí: una CPU (que ejecuta el
programa), una memoria (que almacena el programa y los datos) y unos periféricos (que interaccionan con el
mundo exterior).
Los buses son los elementos que interconectan estos bloques, distinguiéndose al menos un bus de direcciones
(trasporta la dirección del elemento sobre el que se desea actuar), un bus de datos (trasporta el dato con el que se
desea operar) y un bus de control (trasporta las señales de control necesarias para la correcta operación del
sistema).

T8.4
Se muestra en la diapositiva estos elementos en el caso del microcontrolador MSP430G2533.

T8.5
Para que el sistema opere correctamente, es necesario que todos los elementos del mismo (registros especiales de
la CPU, registros de configuración de los periféricos, posiciones de memoria…) dispongan de una dirección única
para poder referenciarlos y realizar operaciones con los mismos (esta dirección es la que trasporta el bus de
direcciones).
Se conoce como mapa de memoria al esquema donde se detalla la dirección que tiene asignada cada elemento
del sistema. Evidentemente esta dirección debe ser única para cada elemento y cada elemento debe tener una
única dirección, conociéndose esta propiedad como exclusividad.
Es importante no confundir el mapa de memoria con la capacidad de direccionamiento. El número máximo de
direcciones que puede utilizar un sistema se conoce como capacidad de direccionamiento, y viene determinado
por el tamaño del bus de direcciones. El microcontrolador MSP430G2533 tiene un bus de direcciones de 16 bits,
por lo que podría utilizar hasta 65536 direcciones distintas, y, por lo tanto, 65536 elementos distintos. No obstante,
es extraño encontrar un microcontrolador que utilice el rango completo de direcciones que puede tener, quedando
normalmente varias direcciones sin utilizar en el sistema. Por lo tanto, el mapa de memoria (que son las direcciones
realmente utilizadas) suele ser menor que la capacidad de direccionamiento (rango completo de direcciones que
puede utilizar).

1
Microcontroladores – Grado en Sistemas de Telecomunicación – Curso 2019/2020 Tema 8: Arquitectura

T8.6
El mapa de memoria se describe en el documento de la familia (común para todos los microcontroladores de la
familia 2) y en el datasheet del microcontrolador (particularizando para el MSP430G2533). En dicho mapa de
memoria se localizan todos los recursos del sistema (registros, memoria…) existiendo también zonas sin utilizar.
Normalmente se localizan los distintos elementos en zonas comunes (registros de 8 bits, registros de 16 bits,
memoria RAM…), lo que simplifica el diseño del sistema.

T8.7
Una descripción más detallada de las distintas zonas del mapa de memoria es la que se realiza a continuación:
• Registros especiales (16 direcciones desde 0x0000 hasta 0x000F): contiene algunos registros de 8 bits de
la CPU que se utilizan con los periféricos (IE1, IE2, IFG1, IFG2).
• Registros 8 bits (240 direcciones desde 0x0010 hasta 0x00FF): contiene los registros de configuración de
los periféricos de 8 bits.
• Registros 16 bits (256 direcciones desde 0x0100 hasta 0x01FF): contiene los registros de configuración de
los periféricos de 16 bits.
• Memoria RAM (512 direcciones desde 0x0200 hasta 0x03FF): contiene la memoria RAM del sistema.
• Información de calibración (256 direcciones desde 0x1000 hasta 0x10FF): contiene una memoria Flash con
la información de calibración introducida por el fabricante (frecuencias de oscilación calibradas e
información de calibración del ADC).
• Memoria Flash (16384 direcciones desde 0xC000 hasta 0xFFFF): contiene la memoria Flash donde se
almacena el programa. Los últimos 64 bytes (direcciones desde 0xFFC0 hasta 0xFFFF) almacenan la Tabla
de Vectores de Interrupción (esto se describe en el apartado 5).
Toda esta información la gestiona el compilador, pues se encuentra disponible en las correspondientes etiquetas
del fichero de cabecera, por lo que normalmente no es necesario conocer estos detalles a la hora de realizar la
programación del microcontrolador.

T8.8 .. T8.12
Se presentan las correspondientes direcciones de cada zona del mapa de memoria según la información del
datasheet del microcontrolador.

T8.13
Continuamos con el análisis de la organización de la memoria.

T8.14
La memoria del microcontrolador MSP430G2533 se divide en dos bloques:
• Memoria RAM (512 bytes desde 0x0200 hasta 0x03FF): destinada a almacenar los datos del programa.
• Memoria Flash (16 Kbytes desde 0xC000 hasta 0xFFFF): destinada a almacenar el programa.

T8.15
En los sistemas basados en microcontrolador (también aplicable a microprocesadores) existen dos alternativas
principales a la hora de conectar la CPU con la memoria:
• Arquitectura Harvard: separa claramente la memoria que almacena el programa de la memoria que
almacena los datos, permitiendo acceder a ambas en paralelo mediante dos buses de direcciones y de
datos. Es una arquitectura más eficiente pero más compleja, por lo que se utiliza en sistemas de altas
prestaciones.

2
Microcontroladores – Grado en Sistemas de Telecomunicación – Curso 2019/2020 Tema 8: Arquitectura

T8.16
• Arquitectura Von Neumann: trata por igual la memoria que almacena el programa y la memoria que
almacena los datos, por lo que únicamente se puede acceder a una de ellas cada vez mediante el bus de
direcciones y de datos. Es una arquitectura no tan eficiente pero mucho más sencilla, por lo que se utiliza
en la gran mayoría de los microcontroladores y microprocesadores.

T8.17
Evidentemente, el microcontrolador MSP430G2533 utiliza una arquitectura Von Neumann, que da lugar a sistemas
(CPUs) más sencillas de implementar y, por lo tanto, más baratos.

T8.18
Independientemente de la arquitectura utilizada al conectar la CPU y la memoria, queda por resolver el problema
de acceder a datos mayores de 8 bits (1 byte) en la memoria, ya que el byte es la unidad que utiliza la memoria para
almacenar/recuperar datos.
El microcontrolador utilizado es de 16 bits, por lo que el tamaño natural de los datos con los que opera (que se
conoce como longitud de palabra) es de 16 bits. No obstante, aunque la CPU del microcontrolador utilizado es de
16 bits, puede realizar operaciones de 8 bits de forma natural con las propias instrucciones que posee (también
puede realizar operaciones de más de 16 bits, pero requiere la ejecución de distintas instrucciones consecutivas).
Cuando se utilizan datos de 16 bits (también conocidos como palabras), se conoce como byte más significativo el
que se encuentra en la parte más alta del dato (el de mayor peso) y como byte menos significativo el que se
encuentra en la parte más baja del dato (el de menor peso). Igualmente, dentro de 1 byte se conoce como bit más
significativo al que se encuentra en la parte más alta del dato (el de mayor peso) y como bit menos significativo al
que se encuentra en la parte más baja del dato (el de menor peso).

T8.19
A la hora de almacenar palabras (datos de 16 bits) en memoria, la cual está estructurada en bytes, hay que decidir
qué posiciones de memoria (bytes) debe ocupar la palabra. Esta característica se denomina endianness, y existen
dos alternativas:
• Little endian: almacena primero (en las posiciones de memoria más bajas) el byte menos significativo de la
palabra.
• Big endian: almacena primero (en las posiciones de memoria más bajas) el byte más significativo de la
palabra.
No hay ninguna ventaja en utilizar un formato u otro, pero los microcontroladores y microprocesadores utilizan
uno u otro. El microcontrolador MSP430G2533 utiliza el formato little endian.
Toda esta información también la gestiona el compilador, pues conoce el formato utilizado por la CPU a la hora de
almacenar palabras en la memoria, por lo que normalmente no es necesario conocer estos detalles a la hora de
realizar la programación del microcontrolador.

T8.20
Seguimos con la descripción de los aspectos más importantes de la CPU.

T8.21
La CPU es sin duda el elemento más importante (y complejo) del microcontrolador, pues se encarga del correcto
funcionamiento del sistema completo.

3
Microcontroladores – Grado en Sistemas de Telecomunicación – Curso 2019/2020 Tema 8: Arquitectura

T8.22
Entre los aspectos más importantes que hay que describir de la CPU se encuentran:
• Arquitectura con la que está desarrollada la CPU.
• Registros de los que dispone para su funcionamiento.
• Modos de direccionamiento para acceder a los datos del sistema.
• Conjunto de instrucciones que puede de ejecutar.

T8.23
En lo referente a la arquitectura con la que está diseñada la CPU, existen básicamente dos alternativas:
• CISC: consiste en diseñar la CPU para poder ejecutar muchas instrucciones muy complejas (por ejemplo:
coger varios datos, desplazarlos, sumarlos y almacenar el resultado, todo con la misma instrucción). Se
obtienen así CPUs complejas, que aunque más potentes tienen el inconveniente de dificultar el paralelismo
en la ejecución de las instrucciones (pipeline), y con ello su eficiencia.
• RISC: consiste en diseñar la CPU para ejecutar muy pocas instrucciones muy simples. Se obtienen así CPUs
sencillas, que aunque no tan potentes pueden implementar fácilmente el paralelismo en la ejecución de
las instrucciones (pipeline), siendo más eficientes.
Los microcontroladores y algunos microprocesadores utilizan la arquitectura RISC, por dar lugar a sistemas sencillos.

T8.24
Evidentemente, el microcontrolador MSP430G2533 utiliza una arquitectura RISC, que da lugar a sistemas (CPUs)
más sencillas de implementar y, por lo tanto, más eficientes.

T8.25
En relación con los registros de la CPU, dispone de 16 registros internos (denominados R0 a R15), que permiten
almacenar valores al igual que la memoria. No obstante, a diferencia de esta última, son mucho más rápidos a la
hora de almacenar/acceder a los datos que contienen, pues se encuentran dentro de la CPU y no es necesario
utilizar los buses de dirección y de datos para acceder a la memoria y traer un dato que se encuentre allí
almacenado.
De estos 16 registros, los 4 primeros (R0 a R3) los utiliza la propia CPU para su correcto funcionamiento, estando
los 12 restantes (R4 a R15) a disposición del programa para almacenar valores. Se analiza a continuación el
funcionamiento de estos 4 registros utilizados por la CPU durante su funcionamiento.

T8.26
El registro R0 se conoce como contador de programa PC (“Program Counter”). Este registro contiene la dirección
de memoria donde se encuentra la siguiente instrucción que se va a ejecutar, y debe ser convenientemente
inicializado al arrancar el sistema con la dirección de la primera instrucción del programa “main” (esto se verá más
adelante en el apartado 5).
Una vez inicializado el registro PC se aumenta automáticamente cada vez que se ejecuta una instrucción,
sumándole el tamaño en bytes de la instrucción que se acaba de ejecutar (como se describirá en el apartado 3.4,
las instrucciones ocupan entre 1 y 3 palabras, es decir, entre 2 y 6 bytes). Igualmente, cuando se realiza un salto
(por ejemplo con un “if”) o se ejecuta una función o una Rutina de Tratamiento de Interrupción o RTI, el valor de
este registro se modifica para apuntar a la siguiente instrucción que debe ser ejecutada.
En todo momento, pues, este registro sigue el orden de ejecución del código, y constituye la única información que
tiene la CPU del código: la siguiente instrucción que va a ejecutar. El resto del código es totalmente desconocido
para la CPU hasta que lo ejecute.

4
Microcontroladores – Grado en Sistemas de Telecomunicación – Curso 2019/2020 Tema 8: Arquitectura

T8.27
El registro R1 se conoce como puntero de pila SP (“Stack Pointer”). Este registro contiene la dirección de memoria
donde se encuentra la parte superior de la pila del sistema, que es una zona de la memoria que se utiliza para
almacenar datos temporales (como por ejemplo la dirección de retorno a la que hay que regresar tras ejecutar una
función).
La pila es simplemente una zona de la memoria RAM que se reserva para ser usada por el sistema. Sigue una filosofía
LIFO (“Last In First Out”), es decir, que los datos se almacenan “apilados” uno encima de otro (en posiciones de
memoria consecutivas), siendo posible acceder únicamente al último dato. Es precisamente la dirección de
memoria donde se encuentra este último dato lo que se almacena en el puntero de pila SP.

T8.28
En el microcontrolador MSP430G2533 la pila se sitúa al final de la memoria RAM, denominándose base de la pila
BOS (“Bottom Of Stack”) a la primera posición de la misma. A partir de esa posición los datos se irán almacenando
consecutivamente, aunque en orden decreciente (es decir, en posiciones menores de memoria), apuntando en
cada momento el puntero de pila al último dato introducido. Esto implica que la pila está implementada “al revés”,
es decir, empieza vacía en una posición de memoria (BOS) y se va rellenando hacia “abajo”, ocupando posiciones
de memoria menores.
El motivo de almacenar la pila “al revés” se debe a que normalmente las variables del código se reservan al principio
de la memoria RAM, por lo que al ir definiendo variables se va ocupando mayor memoria del sistema desde el
principio en adelante. Poner la pila “al revés” comenzando al final de la memoria RAM y creciendo “hacia abajo”
(direcciones de memoria menores) permite que tanto las variables como la pila crezcan en la RAM pero sin
solaparse (ya que están lo más alejadas entre sí que es posible).
La pila es fundamental en la operación de las interrupciones, pues se encarga de almacenar tanto la dirección de
memoria de la siguiente instrucción a ejecutar (PC) al finalizar la RTI como el registro de estado (SR) original a
restaurar (esto se verá más adelante en el apartado 5).

T8.29
Las instrucciones básicas para operar con la pila son PUSH (introduce un nuevo dato en la pila, actualizando el
puntero de pila) y POP (extrae un dato de la pila, actualizando el puntero de pila), las cuales operan únicamente
con palabras (2 bytes). Estas instrucciones, además, operan con predecremento para el PUSH (reducen en 1 palabra
el puntero de pila SP antes de introducir un dato) y postincremento para el POP (aumentan en 1 palabra el puntero
de pila SP después de extraer un dato), lo que hace que la pila esté “al revés” y crezca hacia “abajo”. De hecho, este
comportamiento de predecremento para el PUSH (reducir el puntero de pila antes de introducir un dato) implica
que la base de la pila BOS no tenga ningún dato.
Por lo tanto, la pila se debe concebir como una zona de memoria disponible para almacenar datos de forma
temporal, donde los datos se almacenan (PUSH) y se recuperan (POP) de forma “apilada”, es decir, sólo se puede
acceder al último dato introducido, que es el que está “arriba” de la pila (en verdad, “abajo”, al estar la pila “al
revés”). Se puede asimilar su funcionamiento a una pila de CDs, donde se van introduciendo los CDs pero sólo se
puede extraer el último. La única diferencia es que, para implementar la pila del MSP430G2533, esa pila de CDs
estaría invertida (“boca abajo”).
De nuevo esta información la gestiona el compilador, pues conoce la estructura y la utilización de la pila en el
sistema, por lo que normalmente no es necesario conocer estos detalles a la hora de realizar la programación del
microcontrolador.

5
Microcontroladores – Grado en Sistemas de Telecomunicación – Curso 2019/2020 Tema 8: Arquitectura

T8.30
El registro R2 se conoce como registro de estado SR (“Status Register”). Este registro contiene información sobre
el resultado de las operaciones aritméticas ejecutadas (imprescindibles para implementar instrucciones
condicionales o bucles en función de comparaciones, como “if” o “for”), la habilitación de las interrupciones
enmascarables (GIE) y el modo de bajo consumo en el que se encuentra el sistema.
La utilización de este registro ya se ha descrito en el Tema 5 de Interrupciones y en el Tema 6 de Bajo consumo.

T8.31
Cada uno de los bits del registro de estado SR tiene un determinado significado, que la CPU utilizar para controlar
diversos aspectos de su funcionamiento (saltos condicionales, bucles, interrupciones, bajo consumo…).

T8.32
El registro R3 se conoce como generador de constantes CG (“Constant Generator”). Se utiliza para optimizar el
código generado, simplificando el tamaño y el tiempo de ejecución de algunas instrucciones.

T8.33
El resto de registros (R4 a R15) son de propósito general y están a disposición del programa para almacenar datos.
Son utilizados por el compilador para almacenar variables, por lo que normalmente no es necesario conocer estos
detalles a la hora de realizar la programación del microcontrolador.
Es importante comprender que los datos almacenados en los registros tienen un tiempo de acceso mucho menor
que los datos almacenados en la memoria, por lo que normalmente el compilador analiza cuáles son las variables
del código más utilizadas para almacenarlas si es posible en los registros de propósito general, reduciendo así el
tiempo de ejecución del código.

T8.34 .. T8.41
Los modos de direccionamiento hacen referencia a la forma en la que la CPU puede acceder a los datos
almacenados en el sistema (registros, memoria…). Son la base que soporta la utilización posterior de punteros,
variables, etiquetas… En el microcontrolador MSP430G2533 existen 7 modos de direccionamiento.
El uso de los modos de direccionamiento también la gestiona el compilador, pues conoce los modos de
direccionamiento disponibles en la CPU y la ubicación de los datos, por lo que normalmente no es necesario conocer
estos detalles a la hora de realizar la programación del microcontrolador.

T8.42 .. T8.81
Las instrucciones definen el conjunto de operaciones que puede realizar la CPU sobre los datos. Están codificadas
en código máquina, que es un patrón de “0s” y “1s” que las identifican. En total existen 27 instrucciones, aunque
algunas se han renombrado de otra forma para permitir simplificar el desarrollo de código en ensamblador (son las
instrucciones emuladas).
Las instrucciones tienen una longitud entre 1 y 3 palabras (2 y 6 bytes), en función del tipo de instrucción y de los
datos (operandos) con los que realiza operaciones. La primera palabra siempre se corresponde con el código de
operación (que es un número que identifica la instrucción), y las siguientes palabras se corresponden con los datos
sobre los que operar (ninguna instrucción del MSP430G2533 puede operar con más de dos operandos). Además,
todas las instrucciones tardan entre 1 y 6 ciclos de reloj (de la señal MCLK que controla la CPU) en ejecutarse, en
función de las operaciones que realicen y de los operandos que tengan.
De todas las instrucciones existentes, es interesante señalar las que operan a nivel de bit (T8.78), entre las que se
encuentran las instrucciones BIC, BIS y BIT, que permiten poner a “0”, a “1” o comprobar respectivamente el valor
de un bit de un dato. Son las equivalentes a las operaciones con máscaras “&=”, “|=” y “&”, y denotan la importancia

6
Microcontroladores – Grado en Sistemas de Telecomunicación – Curso 2019/2020 Tema 8: Arquitectura

en los microcontroladores de poder alterar los bits de los datos individualmente, que como se ha comentado en
numerosas ocasiones es la base de la configuración de los periféricos.
También es muy importante notar que no existe ninguna instrucción que detenga la ejecución de la CPU. Esto
significa que la CPU siempre está ejecutando instrucciones de forma continua, según le indique el registro contador
de programa PC que se va actualizando automáticamente cada vez que ejecuta una instrucción para apuntar a la
siguiente. Pero entonces… ¿cómo se le puede indicar a la CPU que se ha llegado al final del programa “main”?
Simplemente, no se puede. En la programación de microcontroladores hay que asegurarse de que el programa
principal nunca termine, para lo cual es necesario insertar algún bucle infinito o modo de bajo consumo del que no
se salga que impida continuar ejecutando instrucciones de la memoria más allá de la última instrucción del
programa.
El uso adecuado de las diferentes instrucciones también la gestiona el compilador, que es el que traduce las
instrucciones en C a las instrucciones disponibles en la CPU, por lo que normalmente no es necesario conocer estos
detalles a la hora de realizar la programación del microcontrolador.

T8.82
Continuamos con el análisis del mecanismo de reset.

T8.83
El reset pretende introducir al sistema en un estado inicial conocido, inicializando para ello con el mismo valor
todos los recursos del microcontrolador.

T8.84
En el microcontrolador MSP430G2533 existen dos tipos de reset que generan un reinicio del sistema:
• POR (“Power-On Reset”): debido a la ocurrencia de determinadas acciones asociadas al hardware.
• PUC (“Power-Up Clear”): debido a la ocurrencia de determinadas acciones asociadas al software.

T8.85
El reset POR está asociado con la conexión del dispositivo a una fuente de alimentación o con la aparición de un
flanco de bajada en el pin RST/NMI del microcontrolador (al que se le suele conectar un pulsador, que permite
forzar el reset).

T8.86
El reset PUC está asociado con la finalización de la cuenta del Watchdog (cuando se utiliza en modo Watchdog) y
con distintos errores que pueden ocurrir en el sistema (violación de las claves de seguridad del Watchdog o de la
Flash, o intento de ejecución de una instrucción cuya dirección se encuentre en la zona del mapa de memoria donde
se ubican los registros de configuración de los periféricos). También se genera un reset PUC después de generar un
reset POR.

T8.87
Cuando se genera un reset, sea del tipo que sea, se realizan una serie de acciones que inicializan al sistema en un
determinado estado: todos los pines se conectan a los Puertos E/S (excepto P2.6 y P2.7, que se conectan al cristal
de cuarzo) y se configuran como entradas; se inicializa el registro de estado SR; se activa el Watchdog (en modo
Watchdog) con unos 30ms de cuenta; y se inicia el registro contador de programa PC con la dirección de la primera
instrucción del programa “main” a ser ejecutada (que está almacenada en el Vector de Interrupción de la
interrupción Reset, como se describirá en el apartado 5).

7
Microcontroladores – Grado en Sistemas de Telecomunicación – Curso 2019/2020 Tema 8: Arquitectura

T8.88
Además, los registros de configuración de todos los periféricos se inicializan a un valor determinado. Esta es la
única diferencia que existe entre un reset POR y un reset PUC, pues algunos valores se inicializan con el POR pero
no con el PUC. Esta información se muestra en todos los registros de configuración de los periféricos, según una
leyenda que se describe en la documentación. En concreto, los valores “(0)” y “(1)” (con paréntesis) que se
muestran en los registros indican valores que se inicializan tras un POR, mientras que los valores “0” y “1” (sin
paréntesis) indican valores que se inicializan tras un PUC.
Hay que tener cuidado con esta nomenclatura, pues hay que recordar que un reset POR genera automáticamente
un reset PUC (esto no ocurre al revés, es decir, un reset PUC no genera un reset POR). Así pues, los valores “(0)” y
“(1)” se inicializan sólo con un POR, pero los valores “0” y “1” se inicializan siempre, tanto por un PUC como por un
POR (que después genera un PUC).

T8.89
Por último se va a realizar una descripción detallada del tratamiento de las interrupciones.

T8.90
Como ya se describió en el Tema 5 de Interrupciones, las interrupciones son señales que se activan en el
microcontrolador para indicar la ocurrencia de determinadas acciones. Estas señales permiten que la CPU detenga
la ejecución del programa para pasar a ejecutar otro código (conocido como Rutina de Tratamiento de Interrupción
o RTI) que gestione la interrupción que se ha generado. Las interrupciones son imprescindibles en cualquier
microcontrolador, pues permiten implementar una aplicación de forma eficiente eliminando el sondeo a la vez que
posibilitan el desarrollo del bajo consumo en el sistema.

T8.91
En el MSP430G2533 existen tres tipos de interrupciones:
• Reset: se genera cuando se produce un reset POR o un reset PUC.
• (No) enmascarables: se generan cuando ocurren determinados errores en el microcontrolador.
• Enmascarables: las generan los periféricos cuando detectan la ocurrencia de determinadas acciones en el
mundo exterior (son las que se describieron en el Tema 5 de Interrupciones).

T8.92
La interrupción de reset es muy importante, pues al estar asociada al reset del sistema es parte del proceso de
inicialización del mismo. En concreto, el Vector de Interrupción de esta interrupción tiene almacenada la dirección
de memoria donde se encuentra la primera instrucción del programa “main” que se debe ejecutar (esto se
describirá con mayor detalle en el apartado 5.2). Esta interrupción no se puede deshabilitar (no dispone de bit de
habilitación), por lo que siempre que ocurre se procesa.

T8.93
Las interrupciones (no) enmascarables se generan ante determinados errores en la operación del sistema (fallo en
los osciladores del sistema o en el acceso a la memoria Flash). Su nombre (no) enmascarables proviene del hecho
de que se pueden deshabilitar mediante sus bits de habilitación específicos, pero no mediante el bit GIE del registro
de estado SR.

T8.94
Las interrupciones enmascarables son las asociadas a los periféricos, y como se describió en el Tema 5 de
Interrupciones pueden deshabilitarse mediante sus bits de habilitación específicos y mediante el bit GIE del registro
de estado SR.

8
Microcontroladores – Grado en Sistemas de Telecomunicación – Curso 2019/2020 Tema 8: Arquitectura

T8.95
Llegados a este punto falta por determinar cómo es capaz de conocer la CPU la ubicación de la Rutina de
Tratamiento de Interrupción o RTI asociada a cada interrupción. En el código cada RTI se identifica por la
combinación de la directiva “#pragma vector” y de la palabra clave “__interrupt” a la hora de definir las funciones
que formarán luego las RTIs, pero ¿cómo traduce el compilador esa información a un esquema que le permita a la
CPU conocer la dirección de la primera instrucción de código de la RTI? Ampliando esta pregunta… ¿cómo sabe la
CPU dónde se encuentra la primera instrucción del código “main”? ¿Tiene que ser quizás la primera posición
disponible de la Flash, 0xC000?
La respuesta a estas preguntas se encuentra en los Vectores de Interrupción, que son una parte imprescindible de
la operación del sistema.

T8.96
Un Vector de Interrupción es simplemente un “puntero”, un valor que apunta a la dirección de memoria donde se
encuentra la primera instrucción del código correspondiente a cada Rutina de Tratamiento de Interrupción o RTI
(este “puntero” debe ser de 16 bits, es decir, debe ocupar una palabra, pues el código a ejecutarse debe ubicarse
en la Flash del sistema, que en el mapa de memoria se encuentra en las 16384 direcciones desde 0xC000 hasta
0xFFFF). Evidentemente, debe existir un Vector de Interrupción por cada interrupción del sistema, y toda esta
información se encuentra ubicada en una zona del mapa de memoria conocida como Tabla de Vectores de
Interrupción o TVI.
La Tabla de Vectores de Interrupción se encuentra ubicada al final del mapa de memoria, concretamente en los
últimos 64 bytes (64 direcciones desde 0xFFC0 hasta 0xFFFF) donde se encuentra la memoria Flash (y, por lo tanto,
constituye información que no se borra, al igual que el programa pues es parte de él). Para que el sistema funcione
correctamente es imprescindible completar la Tabla de Vectores de Interrupción con las direcciones de memoria
de la primera instrucción de todas las interrupciones que se utilicen. Las interrupciones que no se utilicen no se
deben inicializar al no tener código asociado y no ejecutarse nunca, por lo que se inicializan por defecto al valor
0xFFFF para indicar precisamente que no están inicializadas (es imposible que una RTI comience en la posición
0xFFFF, que es la última posición del mapa de memoria).
Esta labor de inicializar la Tabla de Vectores de Interrupción es responsabilidad del programador, aunque
finalmente vuelve de nuevo a ser el compilador el que lo gestiona, pues conoce tanto la posición de la Tabla de
Vectores de Interrupción como la dirección de la primera instrucción de cada RTI (identificadas por la directiva
“#pragma vector” y por la palabra clave “__interrupt”). Por lo tanto, normalmente no es necesario conocer estos
detalles a la hora de realizar la programación del microcontrolador.

T8.97
La distribución de la Tabla de Vectores de Interrupción ya se presentó en el Tema 5 de Interrupciones, pero allí se
trató como un documento que describía el sistema de interrupciones del sistema. Esto sigue siendo cierto, pero
este documento se corresponde además con la descripción de las últimas 64 posiciones del mapa de memoria
(memoria Flash), donde se encuentra ubicada la Tabla de Vectores de Interrupción.
Como se puede apreciar, cada interrupción tiene asociada una dirección de memoria, descrita en la columna Word
Address. Esta es la posición de memoria donde hay que introducir, para cada interrupción, su Vector de
Interrupción, es decir, la posición de memoria donde se encuentra la primera instrucción de su RTI. Como se ha
comentado esta labor la desarrolla finalmente el compilador, pues al indicar con la directiva “#pragma vector” qué
interrupción se corresponde con el código desarrollado ya conoce cuál es la dirección de memoria asociada en la
Tabla de Vectores de Interrupción que debe completar.
Un último aspecto muy importante de la Tabla de Vectores de Interrupción es el relacionado con la interrupción
de reset del sistema. Como ya se comentó en el apartado 4, existen dos tipos de reset, POR y PUC. La única
diferencia entre ellos radica en el valor al que se inicializan algunos registros del microcontrolador, siendo común
9
Microcontroladores – Grado en Sistemas de Telecomunicación – Curso 2019/2020 Tema 8: Arquitectura

el resto del tratamiento que se hace de ambos reset. Es por ello por lo que ambos reset (POR y PUC) se gestionan
como una misma interrupción del sistema, que por lo tanto tienen asociada una entrada en la Tabla de Vectores
de Interrupción (concretamente la última entrada, que se encuentra en la última palabra de la memoria de la
posición 0xFFFE). En dicha entrada de la Tabla de Vectores de Interrupción hay que almacenar el Vector de
Interrupción de la interrupción reset, es decir, la dirección de memoria de la primera instrucción del código que
quiere ejecutarse cuando se produzca un reset. Este valor debe ser la dirección de memoria de la primera
instrucción del código “main”, que también se encarga de inicializar el compilador. Así pues, cuando se produce un
reset el sistema pasa a ejecutar el código asociado a dicho reset, que no es otro que el propio programa principal
“main”, por lo que comienza la ejecución de dicho código.
Recuérdese que el reset POR se genera cuando se enciende el sistema, por lo que al producirse dicho encendido se
genera automáticamente la interrupción reset, ejecutando por lo tanto la primera instrucción del código “main”
según indica el Vector de Interrupción del reset situado en la Tabla de Vectores de Interrupción.

T8.98
Por último, quedan por describir algunos detalles de implementación en la gestión de las interrupciones. Para ello
se va a presentar el procedimiento completo que realiza el sistema ante la ocurrencia de cualquier interrupción, y
que viene a ampliar el procedimiento simplificado que se describió en el Tema 5 de Interrupciones. El objetivo es
comprender cómo es capaz la CPU de detener la ejecución del programa en curso, ejecutar la RTI asociada a la
interrupción y continuar posteriormente ejecutando el programa a partir de la siguiente instrucción en la que se
había detenido.
Este procedimiento se estructura en 7 pasos para ejecutar la RTI y en 2 pasos para retornar a la ejecución del
programa en curso. A continuación se detallan estos pasos.

T8.99
El procedimiento que permite detener la ejecución del programa en curso y ejecutar la RTI tarda 6 ciclos de reloj
(de la señal MCLK que controla la CPU) en llevarse a cabo. Estos 6 ciclos de reloj son precisamente el motivo por el
cual en la utilización del temporizador en modo continuo se realiza la actualización de la cuenta (que se lleva a cabo
en la RTI) con “TACCRx += (N)” y no con “TACCRx = TAR + (N)”, pues mientras se ejecuta la RTI estos 6 ciclos de reloj
hacen que el TAR siga aumentando (y, por lo tanto, utilizar “TACCRx = TAR + (N)” implicaría usar un TAR mayor del
que ha generado la interrupción, acumulándose este error en sucesivas actualizaciones con “TACCRx = TAR + (N)”).
El procedimiento de atención de una interrupción realiza los siguientes pasos: finaliza la ejecución de la instrucción
en curso (una instrucción no se puede “medio ejecutar”), y se almacenan en la pila primero el contador de
programa PC (que indica la próxima instrucción que se debe ejecutar) y después el registro de estado SR (que indica
el estado en el que se encuentra el sistema: resultado de las operaciones aritméticas, interrupciones, bajo
consumo…).

T8.100
Posteriormente se selecciona la interrupción a atender (si sólo hay una se atiende esa, si hay varias se escoge la de
mayor prioridad), si es de una única fuente se limpia su flag de interrupción, se inicializa el registro de estado SR
(desactivando el bajo consumo de la CPU y deshabilitando las demás interrupciones enmascarables del sistema) y,
por último, se carga en el contador de programa PC (que indica la próxima instrucción a ejecutar) el Vector de
Interrupción (dirección de la primera instrucción de la RTI) almacenada en la Tabla de Vectores de Interrupción,
comenzando así a ejecutarse la RTI.

T8.101
El procedimiento que permite retornar a la ejecución del programa en curso una vez finalizada la RTI tarda 2 ciclos
de reloj (de la señal MCLK que controla la CPU) en llevarse a cabo, y realiza los siguientes pasos: restaura de la pila
el registro de estado SR (es el primer dato que se encuentra en la pila) que se guardó al atender a la interrupción,
10
Microcontroladores – Grado en Sistemas de Telecomunicación – Curso 2019/2020 Tema 8: Arquitectura

devolviendo al sistema a la misma situación en la que se encontraba (resultado de las operaciones aritméticas,
interrupciones, bajo consumo…); y se restaura de la pila el contador de programa PC (es el siguiente dato que se
encuentra en la pila) que se guardó al atender a la interrupción, permitiendo ejecutar la siguiente instrucción que
debía ejecutarse.

T8.102
Para finalizar, se muestra un ejemplo concreto de atención de una interrupción, viendo todos los pasos de los
procedimientos de atención y retorno de la RTI. Para ello se supone que:
• La primera instrucción del código principal “main” se encuentra en la dirección de memoria 0xC000
(comienzo de la Flash), por lo que el Vector de Interrupción de la rutina de interrupción reset es
precisamente 0xC000. Esta información se introduce en la entrada correspondiente a la interrupción reset
de la Tabla de Vectores de Interrupción, que se encuentra en la dirección de memoria 0xFFFE.
• La base de la pila BOS (primera posición de la pila) se encuentra en la dirección de memoria 0x0400 (última
posición de la RAM). Como se ha descrito anteriormente, esta posición no contiene ningún dato, pues antes
de introducir un dato en la pila se decrementa en 1 palabra (2 bytes) este valor. Por lo tanto, el primer dato
de la pila (que en este caso es la palabra 0xC042) se encuentra en la posición de memoria 0x03FE, que es
la posición actual del puntero de pila SP.
• La interrupción que se activa es la correspondiente a TA1CCR0 (TIMER1_A0_VECTOR), como se muestra en
el flag de interrupción CCIFG del registro TA1CCTL0 (se supone que dicha interrupción se encuentra
habilitada).
• La primera instrucción (“CLR.W R4”) de la RTI correspondiente a la interrupción de TA1CCR0 se encuentra
en la dirección de memoria 0xC06A, por lo que el Vector de Interrupción de la rutina de interrupción
TA1CCR0 es precisamente 0xC06A. Esta información se introduce en la entrada correspondiente a la
interrupción TA1CCR0 de la Tabla de Vectores de Interrupción, que se encuentra en la dirección de memoria
0xFFFA.
• La CPU va a ejecutar a continuación la instrucción del programa situada en la posición de memoria 0xC01E
(“MOV.B @R4+,R7”), por lo que este valor es el que se encuentra en el contador de programa PC.

T8.103
Cuando se detecta la interrupción comienza el procedimiento de atención de la interrupción:
1. Finaliza la ejecución de la instrucción actual, por lo que el contador de programa PC se actualiza y apunta
la posición de memoria 0xC020 donde se encuentra la siguiente instrucción a ejecutar (“ADD.W #0x10,R7”).

T8.104
2. Se guarda el contador de programa PC en la pila. Para ello se decrementa en primer lugar el puntero de pila
SP en 1 palabra, apuntando a la posición 0x03FC, y posteriormente se introduce el valor del contador de
programa PC 0xC020 en la pila.

T8.105
3. Se guarda el registro de estado SR en la pila. Para ello se decrementa en primer lugar el puntero de pila SP
en 1 palabra, apuntando a la posición 0x03FA, y posteriormente se introduce el valor del registro de estado
SR 0x010E en la pila.

T8.106
4. Como únicamente está activa la interrupción TA1CCR0 se escoge esa para ser atendida.
5. Como la interrupción TA1CCR0 es de una única fuente se limpia automáticamente su correspondiente flag
de interrupción, ubicado en el bit CCIFG del registro TA1CCTL0.
6. Se inicializa a “0” el registro de estado SR.
11
Microcontroladores – Grado en Sistemas de Telecomunicación – Curso 2019/2020 Tema 8: Arquitectura

T8.107
7. Se carga en el contador de programa PC el Vector de Interrupción 0xC06A guardado en la posición de
memoria 0xFFFA de la Tabla de Vectores de Interrupción, correspondiente a la interrupción TA1CCR0. De
este modo comienza a ejecutarse la primera instrucción de la RTI.

T8.108
8. Cuando finaliza la ejecución del RTI, comienza el procedimiento de retorno de la interrupción.

T8.109
9. Se restaura el registro de estado SR almacenado en la pila. Para ello se copia en primer lugar el valor 0x010E
almacenado en la pila en el registro de estado SR, y posteriormente se incrementa el puntero de pila SP en
1 palabra, apuntando a la posición 0x03FC.

T8.110
10. Se restaura el contador de programa PC almacenado en la pila. Para ello se copia en primer lugar el valor
0xC020 almacenado en la pila en el contador de programa PC, y posteriormente se incrementa el puntero
de pila SP en 1 palabra, apuntando a la posición 0x03FE.
Llegados a este punto, la RTI se ha ejecutado completamente (permitiendo atender la interrupción TA1CCR0
generada), y el programa continúa ejecutando la siguiente instrucción en las mimas condiciones en las que se
encontraba, por lo que a todos los efectos la ejecución de la RTI ha sido “trasparente” de cara al programa.

12

Potrebbero piacerti anche