@ -0,0 +1,468 @@ | |||||
# Interrupciones usando MSP430 GCC Toolchain y teclado 4x4 | |||||
Galván.A , Chávez.G , Agosto 2022. | |||||
------ | |||||
[^]: Para usuarios de Linux | |||||
**Abstract** | |||||
This document aims to show how to use interruptions using a 4x4 matrix keyboard and the MSP430 GCC toolchain in order to compile programms for MSP430 target devices using the Linux command terminal. | |||||
***Important!** The information collected and displayed in this document was tested on the following distributions of Linux: *Ubuntu 22.04 LTS* and *Debian 11* using a *MSP430FR6989* microcontroller.* | |||||
[TOC] | |||||
------ | |||||
## **Introducción** | |||||
El paquete GCC de código abierto es un depurador completo y una cadena de herramientas de compilación C/C++ de código abierto para la creación y depuración de aplicaciones integradas basadas en microcontroladores MSP430. Este compilador soporta todos los dispositivos MSP430 sin limitaciones de tamaño de código y se puede utilizar de forma independiente desde la línea de comandos o dentro de Code Composer Studio v6.0 o posterior [1]. | |||||
*El paquete de instalación incluye lo siguiente:* | |||||
1. Binarios GCC y GDB para Windows y Linux. | |||||
2. Encabezado MSP430 y archivos de enlace. | |||||
3. Código fuente. | |||||
4. GBD Agent Configuration. | |||||
#### Esquemáticos de hardware utilizado | |||||
A continuación, se muestra una imagen de la tarjeta utilizada (MSP430FR6989): | |||||
![1.png](https://i.postimg.cc/3NXN4MRW/msp430fr6989.png) | |||||
En la siguiente figura se muestra el esquemático de la tarjeta anteriormente mencionada. En ella se pueden ubicar los LEDs P1.1 y P9.7. | |||||
![2.png](https://i.postimg.cc/7LjZKPJf/esquematico-MSP430-FR6989.png) | |||||
Salidas del microcontrolador **MSP430FR6989** | |||||
![3.png](https://i.postimg.cc/wxXjkpqj/pines-de-salida.png) | |||||
Teclado matricial 4x4 | |||||
![4x4-switch-matrix](https://i.postimg.cc/rpvb7RJX/4x4-switch-matrix.jpg) | |||||
Esquemático de conexiones del teclado matricial 4x4. | |||||
![schematics](https://i.postimg.cc/nrHCYzNB/schematics.webp) | |||||
#### Creación de directorio | |||||
Se debe crear una carpeta en donde se colocará el código y los archivos necesarios para compilar el programa, en este caso se creó la carpeta **Teclado4x4** como ejemplo. | |||||
> Comando para crear carpetas desde la terminal , el comando **mkdir** + *nombre del directorio*. | |||||
> Comando para encontrar carpetas dentro de la carpeta en la que se encuentra **dir**. | |||||
> Comando para entrar en carpeta **cd**. | |||||
```bash | |||||
$ mkdir Teclado4x4 | |||||
$ dir | |||||
$ cd Teclado4x4 | |||||
``` | |||||
#### Sintaxis de interrupciones | |||||
Para definir una interrupción se usa la siguiente sintaxis: | |||||
```c | |||||
void __attribute__ ((interrupt(INTERRUPT_VECTOR))) INTERRUPT_ISR (void) | |||||
{ | |||||
//CODE | |||||
} | |||||
``` | |||||
#### Código | |||||
El código que se muestra a continuación consiste en encender y apagar el LED P1.1 con la tecla 1 y 2 del teclado matricial y encender y apagar el LED P9.7 con las teclas 3 y 4 respectivamente del microcontrolador MSP430FR6989, este código se utilizará como ejemplo a lo largo del documento. Para poder compilar y depurar el código, es necesario copiar dicho código en un archivo **.c**. | |||||
```c | |||||
#include <msp430fr6989.h> | |||||
char columna = 4; | |||||
char fila = 4; | |||||
int estadoColumna = 0; | |||||
int tecla = 0; | |||||
const unsigned char teclado[4][4]= //[Fila][Columna] | |||||
{{1,2,3,10}, | |||||
{4,5,6,11}, | |||||
{7,8,9,12}, | |||||
{13,0,14,15},}; | |||||
void main(void) | |||||
{ | |||||
PM5CTL0 = 0x0000; //desactiva el modo de alta impedancia | |||||
WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer | |||||
//Del 1 al 4 son salidas (estado inicial = 0) y del 5 al 8 son entradas (resistencia Pull-Up) | |||||
//Configuración de puertos P1 Y P3 | |||||
/* | |||||
Salidas: | |||||
Todas las salidas deben tener estado inical de 1 | |||||
P1.0 -> LED de prueba (rojo) | |||||
P9.7 -> LED de prueba (verde) | |||||
P1.3 -> 1 | |||||
P1.5 -> 2 | |||||
P1.6 -> 3 | |||||
P1.7 -> 4 | |||||
Entradas: | |||||
Todas las entradas deben tener estado inicial de 0, por lo tanto, resistencia Pull-Down | |||||
P3.0 -> 5 | |||||
P3.1 -> 6 | |||||
P3.3 -> 7 | |||||
P3.6 -> 8 | |||||
*/ | |||||
//Puerto de SALIDAS | |||||
P1SEL0 = 0x00; | |||||
P1SEL1 = 0x00; | |||||
P1DIR = 0xE9; //"1110,1001" -> Salidas: P1.3,5,6,7 || P1.0 -> LED de prueba | |||||
P1REN = 0x16; //"0001,0110" No habilita resistencia a las salidas | |||||
P1OUT = 0xE8; //"1110,1000" Asigno un 1 lógico a los puertos de salida||A las entradas se les asigna resist. Pull-Down | |||||
P9SEL0 = 0x00; | |||||
P9SEL1 = 0x00; //SELECCIONAMOS FUNCION COMO I/O DIGITAL | |||||
P9DIR = 0x80; //P9.7-> SALIDA P9.0-P9.6->ENTRADAS | |||||
P9REN = 0x7f; | |||||
P9OUT = 0x00; | |||||
//Puerto de ENTRADAS | |||||
P3SEL0 = 0x00; | |||||
P3SEL1 = 0x00; | |||||
P3DIR = 0xB4;//"1011,0100" -> Entradas: P3.0,1,3,6 | |||||
P3REN = 0x4B; //"0100,1011" Habilito resist. a las entradas | |||||
P3OUT = 0x00; //0xB4 1011,0100 -> Resistencias Pull Down para las entradas (estado inicial de 0) | |||||
P3IE = 0x4B; //"0100,1011" -> Habilitador de interrupciones (sólo se hace en las entradas) | |||||
P3IES = 0x00; //Lecura en Flanco de subida | |||||
P3IFG = 0x00; //Se limpia el proceso | |||||
__enable_interrupt(); | |||||
for(;;){ | |||||
switch(tecla){ | |||||
case 1: | |||||
P1OUT |= 0x01; | |||||
break; | |||||
case 2: | |||||
P1OUT &= ~0x01; | |||||
break; | |||||
case 3: | |||||
P9OUT |= 0x80; | |||||
break; | |||||
case 4: | |||||
P9OUT &= ~0x80; | |||||
break; | |||||
default: | |||||
break; | |||||
} | |||||
}//for infinito | |||||
}//main | |||||
/***************Interrupciones***************/ | |||||
//Las entradas son las que realizan la lectura | |||||
void __attribute__ ((interrupt(PORT3_VECTOR))) PORT3_ISR (void) | |||||
{ | |||||
//** Lectura de entradas (columnas) ** | |||||
//Si el estado de IFG es igual al del puerto 3.0 -> la columna detectada es la 1 | |||||
if(P3IFG == 0x01) //lec = P3IFG; lec &= 0x01; | |||||
columna = 0; | |||||
//Si el estado de IFG es igual al del puerto 3.1 -> la columna detectada es la 2 | |||||
else if(P3IFG == 0x02) | |||||
columna = 1; | |||||
//Si el estado de IFG es igual al del puerto 3.3 -> la columna detectada es la 3 | |||||
else if(P3IFG == 0x08) | |||||
columna = 2; | |||||
//Si el estado de IFG es igual al del puerto 3.6 -> la columna detectada es la 4 | |||||
else if(P3IFG == 0x40) | |||||
columna = 3; | |||||
if(columna!=4){ | |||||
P1OUT &= 0x80; //se posiciona el puerto de salida en P1.7 | |||||
for(fila=4; fila>=0;){ | |||||
//Si el estado de la columna es 1 significa que se encontró la fila (por el paso de corrientre a través del btn) | |||||
switch(columna){ | |||||
case 0: | |||||
estadoColumna = P3IN & 0x01; | |||||
break; | |||||
case 1: | |||||
estadoColumna = P3IN & 0x02; | |||||
break; | |||||
case 2: | |||||
estadoColumna = P3IN & 0x08; | |||||
break; | |||||
case 3: | |||||
estadoColumna = P3IN & 0x40; | |||||
break; | |||||
default: | |||||
break; | |||||
}//switch | |||||
//Si se detecta la fila se para el ciclo y continúa con la siguiente instrucción | |||||
if(estadoColumna){ | |||||
break; | |||||
} | |||||
if(P1OUT == 0x20) | |||||
P1OUT >>= 2; | |||||
else | |||||
P1OUT >>= 1; //se desplaza un bit a la derecha | |||||
fila--; | |||||
}//for | |||||
P1OUT = 0xE8; //"1110,1000" -> Se regresa al estado inicial | |||||
}//if | |||||
//Si se detectó una fila en esa columna, se asigna el valor de tecla | |||||
if(fila) | |||||
tecla = teclado[fila-1][columna]; | |||||
columna = 0; | |||||
estadoColumna = 0; | |||||
P3IFG=0x00; | |||||
}//pragma | |||||
``` | |||||
#### Creación de un archivo .c | |||||
Para crear un archivo **.c** se debe posicionar en el directorio en el que lo desea crear y se debe digitar el comando **vim** *filename.c* (se puede usar cualquier editor de texto). Por fines explicativos, como ejemplo, se creará un archivo **.c** llamado **prueba** en la carpeta **Teclado4x4** (previamente creada). Una vez que se ejecuta el comando mencionado, se abrirá una ventana en la que se deberá copiar el códiogo del programa que se quiere subir a la tarjeta. En nuestro caso se copió el código mencionado anteriormente. | |||||
Una vez copiado el código en el archivo **.c**, se teclea **`Esc`** y después **`shift + :x`** para guardar y salir. | |||||
#### Compilación de un programa desde la termial de Linux | |||||
El programa se puede compilar manualmente desde la terminal indicando las rutas de instalación de las librerías, binarios y demás, o usando un método más sencillo implementando un archivo *Makefile* incluido en los ejemplos por defecto que el paquete contiene. En este documento se muestran los pasos a seguir empleando el segundo método comenzando con la creación de un nuevo proyecto; sin embargo, a continuación, se muestra un ejemplo de compilación manual desde la terminal. | |||||
Ejemplo de compilación de un programa desde la terminal (primer método): | |||||
```bash | |||||
$ ./msp430-elf-gcc -I ~/msp430-gcc/include -L ~/msp430-gcc/include -T ~/msp430-gcc/include/msp430fr6989.ld -mmcu=msp430fr6989 -O2 -g ~/Documentos/Programa1/Ejemplo.c -o ~/Documentos/Programa1/Ejemplo.o | |||||
``` | |||||
Primero se debe dirigir a la dirección en donde se encuentra instalado el paquete *MSP430- GCC* y redireccionarse a la carpeta *bin*. | |||||
Para compilar se coloca ./ seguido de la dirección *msp430-elf-gcc* y después se colocan los parámetros de las banderas (flags) correspondientes a -I, -L, -T, -g, -o, -mmcu. | |||||
Donde: | |||||
- **-I**: se agrega el directorio a la lista de directorios para buscar archivos de encabezado. | |||||
- **-L**: se agregan la ruta en las que ld buscará las bibliotecas del archivo. | |||||
- **-T**: dirección donde se encuentran las librerías del microcontrolador especificando cuales se utilizarán . | |||||
- **-g**: dirección donde se encuentra el archivo .c . | |||||
- **-o**: se especifica la ruta donde se encuentra el archivo .c, con la diferencia que se cambia el .c por .o (output file). | |||||
- **-mmcu**: especifica el microcontrolador que se utilizará. | |||||
## **Creación de un nuevo proyecto** | |||||
------ | |||||
#### Pasos para la creación de un nuevo proyecto | |||||
1. Crear un directorio para el nuevo proyecto. | |||||
2. Insertar el archivo .c que contiene el programa que se subirá a la tarjeta. Para crear un archivo .c vea el apartado **Creación de un archivo .c**. | |||||
3. Dentro de la carpeta que se instaló (msp430-gcc), hay un directorio llamado **examples** que contiene ejemplos predeterminados. Copiar uno de los archivos `Makefile` de los proyectos de ejemplo dentro del directorio de su nuevo proyecto, en este caso, dentro de la carpeta **Teclado4x4**. | |||||
4. Abrir el archivo `Makefile` que copió y cambiar el formato de estructura actual por el que se muestra a continuación. En la variable **OBJECTS** se debe colocar el nombre del programa que se va a subir (archivo .c) respetando la terminación **.o**. En la variable **DEVICE** se debe colocar el nombre del microcontrolador que se usará. | |||||
5. Colocar las rutas de instalación correpondientes para las variables **GCC\_DIR** y **SUPPORT\_FILE\_DIRECTORY**. Las direcciones para las variables son **../../../bin** y **../../../include** respectivamente como se muestra en el siguiente ejemplo. | |||||
Estructura de archivo Makefile: | |||||
```c | |||||
OBJECTS=prueba.o | |||||
GCC_DIR = /home/usuario/msp430-gcc/bin | |||||
SUPPORT_FILE_DIRECTORY = /home/usuario/msp430-gcc/include | |||||
DEVICE = msp430fr6989 | |||||
CC = $(GCC_DIR)/msp430-elf-gcc | |||||
GDB = $(GCC_DIR)/msp430-elf-gdb | |||||
CFLAGS = -I $(SUPPORT_FILE_DIRECTORY) -mmcu=$(DEVICE) -O2 -g | |||||
LFLAGS = -L $(SUPPORT_FILE_DIRECTORY) -T $(DEVICE).ld | |||||
all: ${OBJECTS} | |||||
$(CC) $(CFLAGS) $(LFLAGS) $? -o $(DEVICE).out | |||||
debug: all | |||||
$(GDB) $(DEVICE).out | |||||
``` | |||||
## **Debugging** | |||||
#### **Uso del agente GDB ** | |||||
###### Introducción | |||||
El agente GDB es una herramienta para conectar el GDB con el hardware de destino para depurar el software. El GDB Agent utiliza la pila de depuración MSP430 para conectarse al hardware y proporciona una interfaz al GDB. | |||||
En Windows, se proporciona una consola y una versión de aplicación GUI del agente GDB. Solo la aplicación de consola (terminal de comandos) es compatible con Linux. | |||||
#### Iniciando GDB Agent | |||||
###### Línea de comando | |||||
Abra una terminal de comando y dirijase al directorio de instalación, una vez hecho, ejecute lo siguiente: | |||||
```bash | |||||
$ ./bin/gdb\_agent\_console msp430.dat | |||||
``` | |||||
La aplicación de consola abre un puerto TCP/IP en el equipo local. Muestra el número de puerto en la consola, por defecto, este número de puerto es 55000. | |||||
*Es importante que se deje abierta esta consola hasta terminar de depurar el programa (debugging) para poder conectar el GDB con el GDB Agent.* | |||||
```c | |||||
$ ./bin/gdb\_agent\_console msp430.dat | |||||
CPU Name Port | |||||
-------- ---- | |||||
msp430 :55000 | |||||
Starting all cores | |||||
CPU Name Status | |||||
-------- ------ | |||||
msp430 Waiting for client | |||||
``` | |||||
#### Debugging con GDB | |||||
##### Ejecutar un programa en el debugger | |||||
1. Abra otra terminal de comando y dirijase a la ruta donde se encuentra el directorio con el archivo **.c** y el **`Makefile`** del programa que quiere cargar a la tarjeta. | |||||
2. Escriba el comando **make debug**. Este comando inicia el GDB y espera que se introduzcan comandos, esto es indicado por el puntero **(gdb)**. | |||||
```bash | |||||
usuario@usuario:~/Desktop/Teclado4x4$ make debug | |||||
/home/usuario/msp430-gcc/bin/msp430-elf-gcc -I /home/usuario/msp430-gcc/include -mmcu=msp430fr6989 -Og -Wall -g -L /home/usuario/msp430-gcc/include -Wl,-Map,prueba.map,--gc-sections prueba.o -o msp430fr6989.out | |||||
/home/usuario/msp430-gcc/bin/msp430-elf-gdb msp430fr6989.out | |||||
GNU gdb (Mitto Systems Limited - msp430-gcc 9.3.1.11) 9.1 | |||||
Copyright (C) 2020 Free Software Foundation, Inc. | |||||
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> | |||||
This is free software: you are free to change and redistribute it. | |||||
There is NO WARRANTY, to the extent permitted by law. | |||||
Type "show copying" and "show warranty" for details. | |||||
This GDB was configured as "--host=x86_64-pc-linux-gnu --target=msp430-elf". | |||||
Type "show configuration" for configuration details. | |||||
For bug reporting instructions, please see: | |||||
<http://www.gnu.org/software/gdb/bugs/>. | |||||
Find the GDB manual and other documentation resources online at: | |||||
<http://www.gnu.org/software/gdb/documentation/>. | |||||
For help, type "help". | |||||
Type "apropos word" to search for commands related to "word"... | |||||
Reading symbols from msp430fr6989.out... | |||||
(gdb) | |||||
``` | |||||
3. Conecte el dispositivo. | |||||
4. Escriba el comando **target remote :55000** y presione enter para conectar el GDB con el GDB Agent que se encuentra en la otra terminal de comando que se dejó abierta. En la otra terminal se podrá observar en la consola del GDB Agent que se conectó un dispositivo/cliente. | |||||
```bash | |||||
Reading symbols from msp430fr6989.out... | |||||
(gdb) target remote :55000 | |||||
Remote debugging using :55000 | |||||
0x00004414 in __crt0_start () | |||||
(gdb) | |||||
``` | |||||
Consola del GDB Agent: | |||||
```c | |||||
$ ./bin/gdb\_agent\_console msp430.dat | |||||
CPU Name Port | |||||
-------- ---- | |||||
msp430 :55000 | |||||
Starting all cores | |||||
CPU Name Status | |||||
-------- ------ | |||||
msp430 Waiting for client | |||||
msp430 Client connected...Connecting to Target | |||||
Found USB FET at ttyACM0 | |||||
Target connected...Starting server | |||||
``` | |||||
5. Escriba **load** y presione enter para cargar el programa binario al dispositivo MSP430 que esté usando. | |||||
```bash | |||||
(gdb) load | |||||
Loading section .rodata, size 0x10 lma 0x4400 | |||||
Loading section .data, size 0x2 lma 0x4410 | |||||
Loading section .upper.data, size 0x2 lma 0x4412 | |||||
Loading section .text, size 0x21e lma 0x4414 | |||||
Loading section __interrupt_vector_32, size 0x2 lma 0xffce | |||||
Loading section __reset_vector, size 0x2 lma 0xfffe | |||||
Start address 0x00004414, load size 566 | |||||
Transfer rate: 596 bytes/sec, 94 bytes/write. | |||||
(gdb) | |||||
``` | |||||
6. Escriba el comando **continue** para correr el programa o en su defecto escriba **step** para compilar el programa paso por paso. | |||||
```bash | |||||
(gdb) continue | |||||
Continuing. | |||||
``` | |||||
7. Para parar la ejecución teclee **`Ctrl + C` (^C)**, y para salir del GDB escriba `q`, presione enter y posteriormente escriba `y` y presione enter. | |||||
```bash | |||||
^C | |||||
Program stopped. | |||||
0x000044c8 in main () at prueba.c:69 | |||||
69 break; | |||||
(gdb) q | |||||
A debugging session is active. | |||||
Inferior 1 [Remote target] will be detached. | |||||
Quit anyway? (y or n) y | |||||
Detaching from program: /home/alberto/Desktop/Teclado4x4/msp430fr6989.out, Remote target | |||||
Ending remote debugging. | |||||
[Inferior 1 (Remote target) detached] | |||||
``` | |||||
### **Solución de problemas** | |||||
[^]: En este apartado se muestran las posibles soluciones a los problemas más comunes. | |||||
**Error Make debug* | |||||
```bash | |||||
$ make debug | |||||
Make: *** There is no rule to build the 'debug' target. Tall | |||||
``` | |||||
Instalar make para solucionar el problema mediante el comando : | |||||
```bash | |||||
sudo apt-get install make | |||||
``` | |||||
------ | |||||
**Error 127 makefile debug* | |||||
```bash | |||||
/home/usuario/msp430-gcc/bin/msp430-elf-gdb:error while loading shared libraries: libncursesw.so.5: cannot open shared object file: No such file or directory | |||||
make: *** [Makefile: debug] Error 127 | |||||
``` | |||||
Instalar la libreria *libncursesw.so.5* para solucionar el problema, en caso de que continúe el problema, instalar *libncursesw5-dev* mediante el comando : | |||||
```bash | |||||
sudo apt-get install libncursesw5 | |||||
sudo apt-get inatall libncursesw5-dev (opcional) | |||||
``` | |||||
------ | |||||
### **Referencias** | |||||
[1] Texas Instruments. Msp430-gcc-opensource gcc-open source compiler for msp microcontrollers, 2017. | |||||
@ -1,468 +0,0 @@ | |||||
# Interrupciones usando MSP430 GCC Toolchain y teclado 4x4 | |||||
Galván.A , Chávez.G , Agosto 2022. | |||||
------ | |||||
[^]: Para usuarios de Linux | |||||
**Abstract** | |||||
This document aims to show how to use interruptions using a 4x4 matrix keyboard and the MSP430 GCC toolchain in order to compile programms for MSP430 target devices using the Linux command terminal. | |||||
***Important!** The information collected and displayed in this document was tested on the following distributions of Linux: *Ubuntu 22.04 LTS* and *Debian 11* using a *MSP430FR6989* microcontroller.* | |||||
[TOC] | |||||
------ | |||||
## **Introducción** | |||||
El paquete GCC de código abierto es un depurador completo y una cadena de herramientas de compilación C/C++ de código abierto para la creación y depuración de aplicaciones integradas basadas en microcontroladores MSP430. Este compilador soporta todos los dispositivos MSP430 sin limitaciones de tamaño de código y se puede utilizar de forma independiente desde la línea de comandos o dentro de Code Composer Studio v6.0 o posterior [1]. | |||||
*El paquete de instalación incluye lo siguiente:* | |||||
1. Binarios GCC y GDB para Windows y Linux. | |||||
2. Encabezado MSP430 y archivos de enlace. | |||||
3. Código fuente. | |||||
4. GBD Agent Configuration. | |||||
#### Esquemáticos de hardware utilizado | |||||
A continuación, se muestra una imagen de la tarjeta utilizada (MSP430FR6989): | |||||
![1.png](https://i.postimg.cc/3NXN4MRW/msp430fr6989.png) | |||||
En la siguiente figura se muestra el esquemático de la tarjeta anteriormente mencionada. En ella se pueden ubicar los LEDs P1.1 y P9.7. | |||||
![2.png](https://i.postimg.cc/7LjZKPJf/esquematico-MSP430-FR6989.png) | |||||
Salidas del microcontrolador **MSP430FR6989** | |||||
![3.png](https://i.postimg.cc/wxXjkpqj/pines-de-salida.png) | |||||
Teclado matricial 4x4 | |||||
![4x4-switch-matrix](https://i.postimg.cc/rpvb7RJX/4x4-switch-matrix.jpg) | |||||
Esquemático de conexiones del teclado matricial 4x4. | |||||
![schematics](https://i.postimg.cc/nrHCYzNB/schematics.webp) | |||||
#### Creación de directorio | |||||
Se debe crear una carpeta en donde se colocará el código y los archivos necesarios para compilar el programa, en este caso se creó la carpeta **Teclado4x4** como ejemplo. | |||||
> Comando para crear carpetas desde la terminal , el comando **mkdir** + *nombre del directorio*. | |||||
> Comando para encontrar carpetas dentro de la carpeta en la que se encuentra **dir**. | |||||
> Comando para entrar en carpeta **cd**. | |||||
```bash | |||||
$ mkdir Teclado4x4 | |||||
$ dir | |||||
$ cd Teclado4x4 | |||||
``` | |||||
#### Sintaxis de interrupciones | |||||
Para definir una interrupción se usa la siguiente sintaxis: | |||||
```c | |||||
void __attribute__ ((interrupt(INTERRUPT_VECTOR))) INTERRUPT_ISR (void) | |||||
{ | |||||
//CODE | |||||
} | |||||
``` | |||||
#### Código | |||||
El código que se muestra a continuación consiste en encender y apagar el LED P1.1 con la tecla 1 y 2 del teclado matricial y encender y apagar el LED P9.7 con las teclas 3 y 4 respectivamente del microcontrolador MSP430FR6989, este código se utilizará como ejemplo a lo largo del documento. Para poder compilar y depurar el código, es necesario copiar dicho código en un archivo **.c**. | |||||
```c | |||||
#include <msp430fr6989.h> | |||||
char columna = 4; | |||||
char fila = 4; | |||||
int estadoColumna = 0; | |||||
int tecla = 0; | |||||
const unsigned char teclado[4][4]= //[Fila][Columna] | |||||
{{1,2,3,10}, | |||||
{4,5,6,11}, | |||||
{7,8,9,12}, | |||||
{13,0,14,15},}; | |||||
void main(void) | |||||
{ | |||||
PM5CTL0 = 0x0000; //desactiva el modo de alta impedancia | |||||
WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer | |||||
//Del 1 al 4 son salidas (estado inicial = 0) y del 5 al 8 son entradas (resistencia Pull-Up) | |||||
//Configuración de puertos P1 Y P3 | |||||
/* | |||||
Salidas: | |||||
Todas las salidas deben tener estado inical de 1 | |||||
P1.0 -> LED de prueba (rojo) | |||||
P9.7 -> LED de prueba (verde) | |||||
P1.3 -> 1 | |||||
P1.5 -> 2 | |||||
P1.6 -> 3 | |||||
P1.7 -> 4 | |||||
Entradas: | |||||
Todas las entradas deben tener estado inicial de 0, por lo tanto, resistencia Pull-Down | |||||
P3.0 -> 5 | |||||
P3.1 -> 6 | |||||
P3.3 -> 7 | |||||
P3.6 -> 8 | |||||
*/ | |||||
//Puerto de SALIDAS | |||||
P1SEL0 = 0x00; | |||||
P1SEL1 = 0x00; | |||||
P1DIR = 0xE9; //"1110,1001" -> Salidas: P1.3,5,6,7 || P1.0 -> LED de prueba | |||||
P1REN = 0x16; //"0001,0110" No habilita resistencia a las salidas | |||||
P1OUT = 0xE8; //"1110,1000" Asigno un 1 lógico a los puertos de salida||A las entradas se les asigna resist. Pull-Down | |||||
P9SEL0 = 0x00; | |||||
P9SEL1 = 0x00; //SELECCIONAMOS FUNCION COMO I/O DIGITAL | |||||
P9DIR = 0x80; //P9.7-> SALIDA P9.0-P9.6->ENTRADAS | |||||
P9REN = 0x7f; | |||||
P9OUT = 0x00; | |||||
//Puerto de ENTRADAS | |||||
P3SEL0 = 0x00; | |||||
P3SEL1 = 0x00; | |||||
P3DIR = 0xB4;//"1011,0100" -> Entradas: P3.0,1,3,6 | |||||
P3REN = 0x4B; //"0100,1011" Habilito resist. a las entradas | |||||
P3OUT = 0x00; //0xB4 1011,0100 -> Resistencias Pull Down para las entradas (estado inicial de 0) | |||||
P3IE = 0x4B; //"0100,1011" -> Habilitador de interrupciones (sólo se hace en las entradas) | |||||
P3IES = 0x00; //Lecura en Flanco de subida | |||||
P3IFG = 0x00; //Se limpia el proceso | |||||
__enable_interrupt(); | |||||
for(;;){ | |||||
switch(tecla){ | |||||
case 1: | |||||
P1OUT |= 0x01; | |||||
break; | |||||
case 2: | |||||
P1OUT &= ~0x01; | |||||
break; | |||||
case 3: | |||||
P9OUT |= 0x80; | |||||
break; | |||||
case 4: | |||||
P9OUT &= ~0x80; | |||||
break; | |||||
default: | |||||
break; | |||||
} | |||||
}//for infinito | |||||
}//main | |||||
/***************Interrupciones***************/ | |||||
//Las entradas son las que realizan la lectura | |||||
void __attribute__ ((interrupt(PORT3_VECTOR))) PORT3_ISR (void) | |||||
{ | |||||
//** Lectura de entradas (columnas) ** | |||||
//Si el estado de IFG es igual al del puerto 3.0 -> la columna detectada es la 1 | |||||
if(P3IFG == 0x01) //lec = P3IFG; lec &= 0x01; | |||||
columna = 0; | |||||
//Si el estado de IFG es igual al del puerto 3.1 -> la columna detectada es la 2 | |||||
else if(P3IFG == 0x02) | |||||
columna = 1; | |||||
//Si el estado de IFG es igual al del puerto 3.3 -> la columna detectada es la 3 | |||||
else if(P3IFG == 0x08) | |||||
columna = 2; | |||||
//Si el estado de IFG es igual al del puerto 3.6 -> la columna detectada es la 4 | |||||
else if(P3IFG == 0x40) | |||||
columna = 3; | |||||
if(columna!=4){ | |||||
P1OUT &= 0x80; //se posiciona el puerto de salida en P1.7 | |||||
for(fila=4; fila>=0;){ | |||||
//Si el estado de la columna es 1 significa que se encontró la fila (por el paso de corrientre a través del btn) | |||||
switch(columna){ | |||||
case 0: | |||||
estadoColumna = P3IN & 0x01; | |||||
break; | |||||
case 1: | |||||
estadoColumna = P3IN & 0x02; | |||||
break; | |||||
case 2: | |||||
estadoColumna = P3IN & 0x08; | |||||
break; | |||||
case 3: | |||||
estadoColumna = P3IN & 0x40; | |||||
break; | |||||
default: | |||||
break; | |||||
}//switch | |||||
//Si se detecta la fila se para el ciclo y continúa con la siguiente instrucción | |||||
if(estadoColumna){ | |||||
break; | |||||
} | |||||
if(P1OUT == 0x20) | |||||
P1OUT >>= 2; | |||||
else | |||||
P1OUT >>= 1; //se desplaza un bit a la derecha | |||||
fila--; | |||||
}//for | |||||
P1OUT = 0xE8; //"1110,1000" -> Se regresa al estado inicial | |||||
}//if | |||||
//Si se detectó una fila en esa columna, se asigna el valor de tecla | |||||
if(fila) | |||||
tecla = teclado[fila-1][columna]; | |||||
columna = 0; | |||||
estadoColumna = 0; | |||||
P3IFG=0x00; | |||||
}//pragma | |||||
``` | |||||
#### Creación de un archivo .c | |||||
Para crear un archivo **.c** se debe posicionar en el directorio en el que lo desea crear y se debe digitar el comando **vim** *filename.c* (se puede usar cualquier editor de texto). Por fines explicativos, como ejemplo, se creará un archivo **.c** llamado **prueba** en la carpeta **Teclado4x4** (previamente creada). Una vez que se ejecuta el comando mencionado, se abrirá una ventana en la que se deberá copiar el códiogo del programa que se quiere subir a la tarjeta. En nuestro caso se copió el código mencionado anteriormente. | |||||
Una vez copiado el código en el archivo **.c**, se teclea **`Esc`** y después **`shift + :x`** para guardar y salir. | |||||
#### Compilación de un programa desde la termial de Linux | |||||
El programa se puede compilar manualmente desde la terminal indicando las rutas de instalación de las librerías, binarios y demás, o usando un método más sencillo implementando un archivo *Makefile* incluido en los ejemplos por defecto que el paquete contiene. En este documento se muestran los pasos a seguir empleando el segundo método comenzando con la creación de un nuevo proyecto; sin embargo, a continuación, se muestra un ejemplo de compilación manual desde la terminal. | |||||
Ejemplo de compilación de un programa desde la terminal (primer método): | |||||
```bash | |||||
$ ./msp430-elf-gcc -I ~/msp430-gcc/include -L ~/msp430-gcc/include -T ~/msp430-gcc/include/msp430fr6989.ld -mmcu=msp430fr6989 -O2 -g ~/Documentos/Programa1/Ejemplo.c -o ~/Documentos/Programa1/Ejemplo.o | |||||
``` | |||||
Primero se debe dirigir a la dirección en donde se encuentra instalado el paquete *MSP430- GCC* y redireccionarse a la carpeta *bin*. | |||||
Para compilar se coloca ./ seguido de la dirección *msp430-elf-gcc* y después se colocan los parámetros de las banderas (flags) correspondientes a -I, -L, -T, -g, -o, -mmcu. | |||||
Donde: | |||||
- **-I**: se agrega el directorio a la lista de directorios para buscar archivos de encabezado. | |||||
- **-L**: se agregan la ruta en las que ld buscará las bibliotecas del archivo. | |||||
- **-T**: dirección donde se encuentran las librerías del microcontrolador especificando cuales se utilizarán . | |||||
- **-g**: dirección donde se encuentra el archivo .c . | |||||
- **-o**: se especifica la ruta donde se encuentra el archivo .c, con la diferencia que se cambia el .c por .o (output file). | |||||
- **-mmcu**: especifica el microcontrolador que se utilizará. | |||||
## **Creación de un nuevo proyecto** | |||||
------ | |||||
#### Pasos para la creación de un nuevo proyecto | |||||
1. Crear un directorio para el nuevo proyecto. | |||||
2. Insertar el archivo .c que contiene el programa que se subirá a la tarjeta. Para crear un archivo .c vea el apartado **Creación de un archivo .c**. | |||||
3. Dentro de la carpeta que se instaló (msp430-gcc), hay un directorio llamado **examples** que contiene ejemplos predeterminados. Copiar uno de los archivos `Makefile` de los proyectos de ejemplo dentro del directorio de su nuevo proyecto, en este caso, dentro de la carpeta **Teclado4x4**. | |||||
4. Abrir el archivo `Makefile` que copió y cambiar el formato de estructura actual por el que se muestra a continuación. En la variable **OBJECTS** se debe colocar el nombre del programa que se va a subir (archivo .c) respetando la terminación **.o**. En la variable **DEVICE** se debe colocar el nombre del microcontrolador que se usará. | |||||
5. Colocar las rutas de instalación correpondientes para las variables **GCC\_DIR** y **SUPPORT\_FILE\_DIRECTORY**. Las direcciones para las variables son **../../../bin** y **../../../include** respectivamente como se muestra en el siguiente ejemplo. | |||||
Estructura de archivo Makefile: | |||||
```c | |||||
OBJECTS=prueba.o | |||||
GCC_DIR = /home/usuario/msp430-gcc/bin | |||||
SUPPORT_FILE_DIRECTORY = /home/usuario/msp430-gcc/include | |||||
DEVICE = msp430fr6989 | |||||
CC = $(GCC_DIR)/msp430-elf-gcc | |||||
GDB = $(GCC_DIR)/msp430-elf-gdb | |||||
CFLAGS = -I $(SUPPORT_FILE_DIRECTORY) -mmcu=$(DEVICE) -O2 -g | |||||
LFLAGS = -L $(SUPPORT_FILE_DIRECTORY) -T $(DEVICE).ld | |||||
all: ${OBJECTS} | |||||
$(CC) $(CFLAGS) $(LFLAGS) $? -o $(DEVICE).out | |||||
debug: all | |||||
$(GDB) $(DEVICE).out | |||||
``` | |||||
## **Debugging** | |||||
#### **Uso del agente GDB ** | |||||
###### Introducción | |||||
El agente GDB es una herramienta para conectar el GDB con el hardware de destino para depurar el software. El GDB Agent utiliza la pila de depuración MSP430 para conectarse al hardware y proporciona una interfaz al GDB. | |||||
En Windows, se proporciona una consola y una versión de aplicación GUI del agente GDB. Solo la aplicación de consola (terminal de comandos) es compatible con Linux. | |||||
#### Iniciando GDB Agent | |||||
###### Línea de comando | |||||
Abra una terminal de comando y dirijase al directorio de instalación, una vez hecho, ejecute lo siguiente: | |||||
```bash | |||||
$ ./bin/gdb\_agent\_console msp430.dat | |||||
``` | |||||
La aplicación de consola abre un puerto TCP/IP en el equipo local. Muestra el número de puerto en la consola, por defecto, este número de puerto es 55000. | |||||
*Es importante que se deje abierta esta consola hasta terminar de depurar el programa (debugging) para poder conectar el GDB con el GDB Agent.* | |||||
```c | |||||
$ ./bin/gdb\_agent\_console msp430.dat | |||||
CPU Name Port | |||||
-------- ---- | |||||
msp430 :55000 | |||||
Starting all cores | |||||
CPU Name Status | |||||
-------- ------ | |||||
msp430 Waiting for client | |||||
``` | |||||
#### Debugging con GDB | |||||
##### Ejecutar un programa en el debugger | |||||
1. Abra otra terminal de comando y dirijase a la ruta donde se encuentra el directorio con el archivo **.c** y el **`Makefile`** del programa que quiere cargar a la tarjeta. | |||||
2. Escriba el comando **make debug**. Este comando inicia el GDB y espera que se introduzcan comandos, esto es indicado por el puntero **(gdb)**. | |||||
```bash | |||||
usuario@usuario:~/Desktop/Teclado4x4$ make debug | |||||
/home/usuario/msp430-gcc/bin/msp430-elf-gcc -I /home/usuario/msp430-gcc/include -mmcu=msp430fr6989 -Og -Wall -g -L /home/usuario/msp430-gcc/include -Wl,-Map,prueba.map,--gc-sections prueba.o -o msp430fr6989.out | |||||
/home/usuario/msp430-gcc/bin/msp430-elf-gdb msp430fr6989.out | |||||
GNU gdb (Mitto Systems Limited - msp430-gcc 9.3.1.11) 9.1 | |||||
Copyright (C) 2020 Free Software Foundation, Inc. | |||||
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> | |||||
This is free software: you are free to change and redistribute it. | |||||
There is NO WARRANTY, to the extent permitted by law. | |||||
Type "show copying" and "show warranty" for details. | |||||
This GDB was configured as "--host=x86_64-pc-linux-gnu --target=msp430-elf". | |||||
Type "show configuration" for configuration details. | |||||
For bug reporting instructions, please see: | |||||
<http://www.gnu.org/software/gdb/bugs/>. | |||||
Find the GDB manual and other documentation resources online at: | |||||
<http://www.gnu.org/software/gdb/documentation/>. | |||||
For help, type "help". | |||||
Type "apropos word" to search for commands related to "word"... | |||||
Reading symbols from msp430fr6989.out... | |||||
(gdb) | |||||
``` | |||||
3. Conecte el dispositivo. | |||||
4. Escriba el comando **target remote :55000** y presione enter para conectar el GDB con el GDB Agent que se encuentra en la otra terminal de comando que se dejó abierta. En la otra terminal se podrá observar en la consola del GDB Agent que se conectó un dispositivo/cliente. | |||||
```bash | |||||
Reading symbols from msp430fr6989.out... | |||||
(gdb) target remote :55000 | |||||
Remote debugging using :55000 | |||||
0x00004414 in __crt0_start () | |||||
(gdb) | |||||
``` | |||||
Consola del GDB Agent: | |||||
```c | |||||
$ ./bin/gdb\_agent\_console msp430.dat | |||||
CPU Name Port | |||||
-------- ---- | |||||
msp430 :55000 | |||||
Starting all cores | |||||
CPU Name Status | |||||
-------- ------ | |||||
msp430 Waiting for client | |||||
msp430 Client connected...Connecting to Target | |||||
Found USB FET at ttyACM0 | |||||
Target connected...Starting server | |||||
``` | |||||
5. Escriba **load** y presione enter para cargar el programa binario al dispositivo MSP430 que esté usando. | |||||
```bash | |||||
(gdb) load | |||||
Loading section .rodata, size 0x10 lma 0x4400 | |||||
Loading section .data, size 0x2 lma 0x4410 | |||||
Loading section .upper.data, size 0x2 lma 0x4412 | |||||
Loading section .text, size 0x21e lma 0x4414 | |||||
Loading section __interrupt_vector_32, size 0x2 lma 0xffce | |||||
Loading section __reset_vector, size 0x2 lma 0xfffe | |||||
Start address 0x00004414, load size 566 | |||||
Transfer rate: 596 bytes/sec, 94 bytes/write. | |||||
(gdb) | |||||
``` | |||||
6. Escriba el comando **continue** para correr el programa o en su defecto escriba **step** para compilar el programa paso por paso. | |||||
```bash | |||||
(gdb) continue | |||||
Continuing. | |||||
``` | |||||
7. Para parar la ejecución teclee **`Ctrl + C` (^C)**, y para salir del GDB escriba `q`, presione enter y posteriormente escriba `y` y presione enter. | |||||
```bash | |||||
^C | |||||
Program stopped. | |||||
0x000044c8 in main () at prueba.c:69 | |||||
69 break; | |||||
(gdb) q | |||||
A debugging session is active. | |||||
Inferior 1 [Remote target] will be detached. | |||||
Quit anyway? (y or n) y | |||||
Detaching from program: /home/alberto/Desktop/Teclado4x4/msp430fr6989.out, Remote target | |||||
Ending remote debugging. | |||||
[Inferior 1 (Remote target) detached] | |||||
``` | |||||
### **Solución de problemas** | |||||
[^]: En este apartado se muestran las posibles soluciones a los problemas más comunes. | |||||
**Error Make debug* | |||||
```bash | |||||
$ make debug | |||||
Make: *** There is no rule to build the 'debug' target. Tall | |||||
``` | |||||
Instalar make para solucionar el problema mediante el comando : | |||||
```bash | |||||
sudo apt-get install make | |||||
``` | |||||
------ | |||||
**Error 127 makefile debug* | |||||
```bash | |||||
/home/usuario/msp430-gcc/bin/msp430-elf-gdb:error while loading shared libraries: libncursesw.so.5: cannot open shared object file: No such file or directory | |||||
make: *** [Makefile: debug] Error 127 | |||||
``` | |||||
Instalar la libreria *libncursesw.so.5* para solucionar el problema, en caso de que continúe el problema, instalar *libncursesw5-dev* mediante el comando : | |||||
```bash | |||||
sudo apt-get install libncursesw5 | |||||
sudo apt-get inatall libncursesw5-dev (opcional) | |||||
``` | |||||
------ | |||||
### **Referencias** | |||||
[1] Texas Instruments. Msp430-gcc-opensource gcc-open source compiler for msp microcontrollers, 2017. | |||||