--- title: Práctica 0. Entorno de Desarrollo sobre LEON3 description: Enunciado de la Práctica 0 del laboratorio de Software de Control en Tiempo Real para Sistemas Espaciales de la Universidad de Alcalá tags: SCTRE-MCYTE robots: noindex, nofollow --- # Práctica 0. Entorno de Desarrollo sobre LEON3 <div style="text-align: justify"> Esta práctica describe la utilización de un entorno de trabajo para el desarrollo de software sobre el procesador LEON3 empleando compilación cruzada. El entorno incluye un simulador de este procesador, denominado TSIM2, y una herramienta de depuración, denominada GRMON3, que permite descargar y depurar programas sobre una placa que integre el procesador LEON3. La práctica, además, explica cómo utilizar el *Integrated Development Environment* (IDE) Eclipse para crear nuevos programas, compilarlos y, posteriormente, descargarlos y depurarlos tanto sobre el simulador TSIM2 como sobre una placa que integre el procesador LEON3, empleando para ello GRMON3. El procesador LEON3, de la arquitectura SPARC-V8, resulta de especial interés para esta asignatura dado que, en la última década, ha sido uno de los procesadores de referencia de la Agencia Espacial Europea -European Space Agency (ESA)-, siendo utilizado en muchas de sus misiones espaciales como parte del *On-Board Data Handling* (OBDH). El entorno de trabajo **lo tenéis ya instalado en el laboratorio de la universidad** sobre una maquina virtual construida a partir de una distribución de Linux, concretamente la Ubuntu 22.04. En el guión se dan los pasos de instalación del entorno para esa versión de Ubuntu, por si quisieráis hacer vosotros mismos la instalación desde cero sobre una máquina (virtual o no) que tenga Ubuntu 22.04 como sistema operativo, si bien estos pasos son análogos en el caso de que la distribución de Ubuntu elegida fuera otra. :::info Los comandos que se van a proporcionar para describir la instalación del entorno de trabajo están definidos para el caso en que los archivos descargados se ubiquen en el directorio `/home/atcsol/Downloads`. Para otra ubicación, como `/home/atcsol/Descargas`, será necesario que en los comandos se utilice la ubicación correspondiente. ::: </div> ## Parte 1: Instalación de los paquetes básicos (No realizar en EL5) <div style="text-align: justify"> El entorno de trabajo requiere que estén instalados un conjunto de paquetes. Desde la consola de Ubuntu podéis completar la instalación de estos paquetes con la siguiente secuencia de comandos que deben ser ejecutados de uno en uno. ```shell sudo dpkg --add-architecture i386 sudo apt-get update sudo apt-get install libc6:i386 libncurses5:i386 sudo apt-get install libstdc++6:i386 libnspr4-dev:i386 sudo apt-get install zlib1g:i386 libx11-6:i386 sudo apt-get install build-essential ``` :::info Es posible que todos los paquetes, o parte de ellos, ya estén instalados en la distribución de Ubuntu que utilizáis. En el caso de que alguno de los paquetes NO esté instalado, al ejecutar el comando de instalación se solicitará una confirmación mediante el siguiente mensaje, a la que deberemos responder pulsando la tecla Y. ```shell Do you want to continue [Y/N] ``` ::: </div> ## Parte 2: Instalación del compilador cruzado Bare-C (No realizar en EL5) <div style="text-align: justify"> BCC (*Bare-C Cross Compiler*) es un compilador cruzado para los procesadores de la familia LEON. Este compilador, basado en GCC, permite construir aquellos programas más básicos que no requieran de Sistema Operativo, como el software de arranque (*Boot Software* o BSW) que toma el control de un computador de vuelo tras un reset. La distribución del compilador incluye la biblioteca de C *Newlib standalone* y rutinas de bajo nivel para entrada y salida. La versión 4.2.2 del compilador BCC que utilizaremos en este laboratorio puede descargarse del siguiente enlace: http://www.gaisler.com/anonftp/bcc/bin/linux/sparc-elf-4.4.2-1.0.50.tar.bz2 Una vez descargada esta versión, su instalación comprende los siguientes pasos que deben completarse ejecutando, desde un terminal, los comandos indicados en cada uno de ellos: #### 2.1 - Mover el archivo descargado a `/opt` y descomprimirlo en ese mismo directorio ```shell cd /home/atcsol/Downloads sudo mv sparc-elf-4.4.2-1.0.50.tar.bz2 /opt cd /opt sudo tar xvfj sparc-elf-4.4.2-1.0.50.tar.bz2 -C /opt ``` #### 2.2 - Crear un enlace blando con nombre `sparc-elf` al directorio donde está ubicado el compilador ```shell sudo ln –s sparc-elf-4.4.2 sparc-elf ``` :::info En enlace no se podrá crear si ya existe un enlace con el mismo nombre. En ese caso, antes de crear el enlace deberemos **borrar previamente** el enlace existente con el siguiente comando: ```shell rm sparc-elf ``` ::: </div> ## Parte 3: Instalación del compilador RCC 4.6 (No realizar en EL5) <div style="text-align: justify"> El sistema de compilación cruzada RCC (*RTEMS Cross Compiler*) integra un compilador cruzado para los procesadores LEON3, basado en GCC, junto con una distribución del sistema operativo de tiempo real RTEMS. La versión 4.6.6 de RCC que utilizaremos en este laboratorio puede descargarse del siguiente enlace: http://www.gaisler.com/anonftp/rcc/bin/linux/sparc-rtems-4.6.6-gcc-3.2.3-1.0.20-linux.tar.bz2 Una vez descargada esta versión, su instalación comprende los siguientes pasos que deben completarse ejecutando, desde un terminal, los comandos indicados en cada uno de ellos: #### 3.1 - Mover el archivo descargado a `/opt` y descomprimirlo en ese mismo directorio ```shell cd /home/atcsol/Downloads sudo mv sparc-rtems-4.6.6-gcc-3.2.3-1.0.20-linux.tar.bz2 /opt cd /opt sudo tar xvfj sparc-rtems-4.6.6-gcc-3.2.3-1.0.20-linux.tar.bz2 -C /opt ``` #### 3.2 - Crear un enlace blando con nombre `rtems` al directorio donde está ubicado el compilador ```shell sudo ln –s rtems-4.6 rtems ``` :::info En enlace no se podrá crear si ya existe un enlace con el mismo nombre. En ese caso, antes de crear el enlace deberemos **borrar previamente** el enlace existente con el siguiente comando: ```shell rm rtems ``` ::: </div> ## Parte 4: Instalación del simulador TSIM2 (No realizar en EL5) <div style="text-align: justify"> El simulador TSIM2 permite simular el comportamiento de un *System On Chip* construido a partir del procesador LEON3 y de controladores de interfaces y dispositivos que se integran en la biblioteca GPL de cores denominada [GRLIB](https://www.gaisler.com/index.php/products/ipcores/soclibrary). Esto permite simular, no sólo la ejecución de instrucciones, sino otras funciones básicas de un computador como el control de las interrupciones, la programación de *Timers* y la transmisión y recepción de datos a través de una UART. TSIM2 es una herramienta profesional que tiene una gran implantación en la industria espacial. La versión de evaluación de este simulador se puede encontrar en la página [https://www.gaisler.com](https://www.gaisler.com), si bien, dado que es una versión que tiene una caducidad muy corta, vamos a utilizar una versión específica ejecutada empleando la utilidad *faketime* que nos permite fijar la fecha de ejecución. Para ello, nos descargaremos la versión 3.1.9 del siguiente enlace: https://download.gaisler.com/products/TSIM3/bin/tsim-eval/tsim-eval-3.1.9.tar.gz y el lanzador [tsim-launch](https://universidaddealcala-my.sharepoint.com/:u:/r/personal/o_rodriguez_uah_es/Documents/public/tsim-launch.tar.gz?csf=1&web=1&e=rJudNT) que nos permite emular una fecha de ejecución. Una vez realizadas las descargas, procederemos a la instalación mediante los siguientes pasos que deben completarse ejecutando, desde un terminal, los comandos indicados en cada uno de ellos: #### 4.1 - Mover los archivo descargados a `/opt` y descomprimirlos en ese mismo directorio ```shell cd /home/atcsol/Downloads sudo mv tsim-eval-3.1.9.tar.gz /opt sudo mv tsim-launch.tar.gz /opt cd /opt sudo tar xvfz tsim-eval-3.1.9.tar.gz sudo tar xvfz tsim-launch.tar.gz ``` #### 4.2 - Crear un enlace blando con el nombre `tsim` al lanzador ```shell sudo ln –s tsim-launch/tsim/linux-x64 tsim ``` #### 4.3 - Instalar la utilidad faketime ```shell sudo apt-get install faketime ``` </div> ## Parte 5: Instalación de la herramienta de depuración GRMON3 (No realizar en EL5) <div style="text-align: justify"> La herramienta de depuración GRMON3 nos permite descargar y depurar programas sobre una placa que integre el procesador LEON3. En esta asignatura utilizaremos la placa Nexys A7 basada en la FPGA Arty A7-100T de Xilinx sobre la que se ha sintetizado un SoC que integra un LEON3 y diversos controladores de interfaces y dispositivos de la biblioteca [GRLIB](https://www.gaisler.com/index.php/products/ipcores/soclibrary), ya mencionada anteriormente. La siguiente figura muestra la placa de desarrollo Nexys-A7: <br/> <img width="45%" src="https://hackmd.io/_uploads/BJYkTAXca.png" style="display: block; margin: auto"></img> Para poder controlar la tarjeta es necesario que nos descarguemos e instalemos el driver [digilent.adept.runtime_2.26.1-amd64.deb](https://universidaddealcala-my.sharepoint.com/:u:/r/personal/o_rodriguez_uah_es/Documents/public/digilent.adept.runtime_2.26.1-amd64.deb?csf=1&web=1&e=ra1OEW). El proceso de instalación se inicia pulsando con el botón derecho del ratón sobre el archivo descargado de forma que se despliegue el menú contextual tal como aparece en la siguiente figura: <img width="45%" src="https://hackmd.io/_uploads/SJtlUJ4q6.png" style="display: block; margin: auto"></img> Seleccionando la opción `Abrir con Instalación de software`se abre la siguiente ventana que nos permite completar la instalacíón del driver pulsando en *Instalar*. <img width="45%" src="https://hackmd.io/_uploads/HkNXwJE56.png" style="display: block; margin: auto"></img> Una vez instalado el driver, procederemos a descargarnos la última versión de evaluación de GRMON3 con el siguiente enlace: https://download.gaisler.com/anonftp/grmon/grmon-eval-4.0.2.tar.gz. Tras descargarse el archivo, procederemos con los siguientes pasos de la instalación que deben completarse ejecutando, desde un terminal, los comandos indicados en cada uno de ellos: #### 5.1 - Mover los archivo descargados a `/opt` y descomprimirlos en ese mismo directorio ```shell cd /home/atcsol/Downloads sudo mv grmon-eval-4.0.2.tar.gz /opt cd /opt sudo tar xvfz grmon-eval-4.0.2.tar.gz ``` #### 5.2 - Crear un enlace blando con el nombre `grmon` al directorio donde se encuentran los binarios de la herramienta de depuración ```shell sudo ln -s grmon-eval-4.0.2/linux/bin64 grmon ``` :::info En enlace no se podrá crear si ya existe un enlace con el mismo nombre. En ese caso, antes de crear el enlace deberemos **borrar previamente** el enlace existente con el siguiente comando: ```shell rm grmon ``` ::: </div> ## Parte 6: Configuración del PATH (No realizar en EL5) <div style="text-align: justify"> Para que tanto los compiladores como las aplicaciones TSIM2 y GRMON3 puedan ejecutarse independientemente del directorio de trabajo del usuario, es necesario incluir en el PATH de búsqueda los directorios donde están instaladas de la siguiente forma: ```c= PATH="/opt/sparc-elf/bin:$PATH" PATH="/opt/rtems/bin:$PATH" PATH="/opt/tsim:$PATH" PATH="/opt/grmon:$PATH" ``` Añadiendo esas líneas al final del archivo `.profile` que se encuentra en vuestro directorio de usuario `/home/atcsol`, lograréis que en cada inicio de sesión con vuestro usuario quede el PATH correctamente configurado. Esta edición la podéis hacer con cualquier editor de texto. Los siguientes comandos permiten hacerlo con el editor gedit de fácil utilización. ```shell cd /home/atcsol gedit .profile ``` En la siguiente figura se muestra la edición del archivo .profile con gedit tal como debería quedar (revisar que las comillas son correctas comprobando el resaltado de texto de gedit). </div> <br/> <img width="65%" src="https://hackmd.io/_uploads/r124-Tr5a.png" style="display: block; margin: auto"></img> :::info Antes proseguir, cerrad vuestra sesión actual y volved a iniciar una nueva sesión de forma que se actualice el PATH y se puedan utilizar las aplicaciones instaladas. Además, debéis aseguraros que vuestra configuración de la máquina virtual tiene configurada la compatibilidad USB a 3.1 tal como aparece en la figura siguiente ::: ![Config_VM_USB_3_1](https://hackmd.io/_uploads/ryS5lnU5T.png) ## Parte 7: Creación de un Proyecto Eclipse para LEON3 <div style="text-align: justify"> Una vez completados todos los pasos de instalación anteriores, ya es posible crear proyectos de compilación cruzada para el procesador LEON3. Para ello se ejecutará el *IDE Eclipse* mediante el siguiente icono: ![IconoEclipse](https://hackmd.io/_uploads/rkwLS-Tckg.png) *Eclipse* es un entorno de desarrollo que permite gestionar distintos proyectos. Un proyecto está formado por un conjunto de archivos fuente distribuidos en distintos directorios o carpetas, a partir de los cuales se puede obtener, tras un proceso de construcción (*building*), un archivos binario ejecutable. Eclipse almacena los proyectos activos dentro de un directorio específico denominado *workspace*. Este directorio puede estar localizado en cualquier lugar de nuestro sistema de archivos y llevar cualquier nombre. Al arrancar *Eclipse*, el programa presenta un cuadro de diálogo en el que se solicita al usuario que introduzca la ruta al workspace que se va a utilizar durante la ejecución. En nuestro caso, seleccionaremos la ruta de directorio por defecto, i.e., un directorio llamado eclipse-workspace localizado en el directorio de conexión de nuestro usuario. ![Workspace](https://hackmd.io/_uploads/HytGO-pqJl.png) </div> ## Tarea 1 a realizar: *Hola Mundo* para LEON3 y depuración sobre TSIM2 <div style="text-align: justify"> Como primera toma de contacto con el *IDE Eclipse*, vamos a crear un proyecto sencillo que utilice la salida estándar para un mensaje. Para ello, seleccionamos la opcion **File -> New -> C/C++ Project** del menú principal. Al hacerlo, aparecerá un cuadro de diálogo en el que deberemos seleccionar la plantilla de proyecto que vamos a utilizar. En nuestro caso, vamos a crear un nuevo proyecto en lenguaje C y para ello se utilizará el tipo de proyecto `C Managed Build` tal como aparece en la siguiente figura: </div> <img width="65%" src="https://hackmd.io/_uploads/S17GITB9T.png" style="display: block; margin: auto"></img> <div style="text-align: justify"> A continuación, se determinará el nombre del proyecto (`hola_mundo`) y la toolchain a utilizar, que será del tipo `Cross GCC` para poder indicar una compilación cruzada destinada a obtener un ejecutable para el procesador LEON3. </div> <br/> <img width="65%" src="https://hackmd.io/_uploads/BkEXCarqa.png" style="display: block; margin: auto"></img> <br/> <div style="text-align: justify"> El siguiente paso es seleccionar las dos configuraciones `Debug y Release` que se desean desplegar tal como aparece en la siguiente figura: </div> <br/> <img width="65%" src="https://hackmd.io/_uploads/By_HyCScp.png" style="display: block; margin: auto"></img> <div style="text-align: justify"> En este cuadro se fijará como prefijo de compilación `sparc-elf-` con el fin de utilizar el compilador para la arquitectura `SPARC`, que es la arquitectura del procesador LEON3. Además, se fijará el PATH de compilación `/opt/sparc-elf/bin`, tal como se muestra en la figura. </div> <br/> <img width="65%" src="https://hackmd.io/_uploads/SJcChaB5T.png" style="display: block; margin: auto"></img> <div style="text-align: justify"> Una vez creado el proyecto, se añadirá un nuevo archivo fuente, de nombre `main.c`, seleccionando el menú contextual **New->Source File** sobre el proyecto tal como muestra la siguiente figura: </div> <br/> <img width="75%" src="https://hackmd.io/_uploads/SyuzQfpc1e.png" style="display: block; margin: auto"></img> <br/> <div style="text-align: justify"> Y se le asigna el nombre `main.c`. </div> <br/> <img width="75%" src="https://hackmd.io/_uploads/Sk4uXzT5Je.png" style="display: block; margin: auto"></img> <div style="text-align: justify"> El código a añadir en `main.c`es el siguiente, cuya funcionalidad se reduce a enviar un mensaje de `Hola Mundo`. </div> <br/> ```c= /* * main.c * * Created on: Feb 26, 2025 * Author: atcsol */ #include <stdio.h> int main(){ printf("Hola Mundo\n"); return 0; } ``` <div style="text-align: justify"> Una vez guardado el contenido del archivo `main.c`, generaremos el ejecutable utilizando el menú contextual `Build Project` que se habilita al pulsar el botón derecho sobre el proyecto : </div> <br/> <img width="65%" src="https://hackmd.io/_uploads/HkoBV7acye.png" style="display: block; margin: auto"></img> <div style="text-align: justify"> Y comprobaremos que la compilación se ha completado sin errores en la consola (`Console`) de Eclipse. </div> <img width="80%" src="https://hackmd.io/_uploads/SyM_B7TqJl.png" style="display: block; margin: auto"></img> <div style="text-align: justify"> Tras obtener el ejecutable, podemos lanzar la ejecución del programa en modo depuración creando una nueva Configuración de Depuración (**Debug Configuration**). Para ello, emplearemos el menú contextual del proyecto tal como muestra la siguiente figura: <br/> </div> <img width="80%" src="https://hackmd.io/_uploads/HyTWD76c1l.png" style="display: block; margin: auto"></img> <br/> <div style="text-align: justify"> El menú nos lleva a la vista de depuración (*Debug*) de Eclipse, y desde allí, podemos crear una nueva Configuración de Depuración Hardwarwe basada en GDB (**GDB Hardware Debugging**) eligiendo la opción del menú contextual (botón derecho) *New Configuration*. </div> <br/> <img width="75%" src="https://hackmd.io/_uploads/HyZ3DQaq1g.png" style="display: block; margin: auto"></img> <div style="text-align: justify"> El cuadro de dialogo que se muestra a continuación muestra el nombre del proyecto y el path donde se encuentra el binario. A través de la pestaña *Debugger* de este cuadro se permite, además, determinar cómo gdb se debe conectar al *target* para cargar el programa y poder depurar su ejecución. </div> <br/> <img width="75%" src="https://hackmd.io/_uploads/BkZmoXaq1l.png" style="display: block; margin: auto"></img> <div style="text-align: justify"> La siguiente figura muestra la configuración de esta pestaña `Debugger` para poder cargar y ejecutar programas sobre el simulador TSIM, empleando para ello `sparc-elf-gdb` y el puerto localhost:1234. </div> <img width="75%" src="https://hackmd.io/_uploads/SJGsy4p5kx.png" style="display: block; margin: auto"></img> <br/> <div style="text-align: justify"> Una vez definida la Configuración de Depuración, podemos lanzar la ejecución del programa en modo depuración seleccionando el botón *Debug*. Sin embargo, antes de poder hacerlo, debemos tener arrancado TSIM. Para eso abriremos un nuevo terminal y, desde línea de comando, ejecutaremos: </div> ```shell tsim-leon3 ``` <div style="text-align: justify"> La ejecución correcta hará que aparezca la información sobre JTAG y una línea de comandos interna de TSIM2 indicada con `tsim>`. </div> ![tsim-leon3](https://hackmd.io/_uploads/HkE430Sca.png) <div style="text-align: justify"> Al introducir el comando `gdb` en la línea interna de comandos de TSIM le indicamos que abra un puerto para que GDB se conecte a través de él y pueda descargar y depurar programas. Tal como vemos en la siguiente figura, el puerto que abre TSIM es 1234. </div> ![tsim2_gdb](https://hackmd.io/_uploads/BkbyCCS96.png) <div style="text-align: justify"> Ahora ya podemos volver a Eclipse y pulsar el botón *Debug* para iniciar la depuración. A continuación, Eclipse mostrará un cuadro de diálogo que nos sugiere cambiar de perspectiva, esto es, dejar la perspectiva C/C++, que veníamos utilizando, para pasar a la perspectiva de depuración o Debug. En nuestro caso, vamos a aceptar el cambio pulsando sobre el botón Switch. </div> ![ToDebug](https://hackmd.io/_uploads/H1laXVa5kx.png) <br/> <div style="text-align: justify"> Tras comenzar la depuración, la ejecución del programa por defecto se detiene siempre al comienzo de la función main(). La barra de herramientas de la perspectiva de depuración proporciona un conjunto de botones que nos permiten controlar la ejecución de nuestro programa. </div> ![barra](https://hackmd.io/_uploads/r1G-O4a9yl.png) De entre los botones de la barra de herramientas, destacamos los siguientes: * `Resume`: continúa la ejecución del programa hasta que éste termina o alcanza un punto de ruptura (breakpoint). Los breakpoints se describen más adelante. * `Terminate`: finaliza la sesión de depuración, cerrando el depurador. * `Step into`: ejecuta la siguiente línea de código. Si la línea de código contiene una llamada a una función, el depurador entra dentro de la función y continúa la depuración línea a línea a partir de la primera línea de su código. * `Step over`: ejecuta la siguiente línea de código. Si la línea de código contiene una llamada a la función, ésta es ejecutada por completo y la depuración continúa a partir de la siguiente línea. A continuación, vamos a ejecutar el código completo mediante el botón `Resume`. En TSIM se mostrará el mensaje `Hola Mundo`: ![Hola_MundoOK](https://hackmd.io/_uploads/rySqFNacye.png) Una vez terminada la ejecución, y para poder ejecutar los programas de las siguientes tareas con un estado correcto de TSIM, vamos a asegurarnos que, antes de ejecutar un programa, y desde la línea interna, se utiliza la siguiente secuencia que fuerza un reset del simulador y la apertura del puerto gdb: ```shell reset gdb ``` ## Tarea 2 a realizar: Proyecto para LEON3 con entrada y salida a través de la UART y depuración sobre TSIM2 <div style="text-align: justify"> La segunda tarea a realizar consiste en completar un nuevo proyecto denominado `prac0_obdh_uart_23_24`. Para ello, se utilizará de nuevo la opcion **File -> New -> C/C++ Project** del menú principal, y al determinar el nombre del proyecto se fijará como `prac0_obdh_uart_23_24`, siendo la toolchain a utilizar de tipo `Cross GCC`, indicando así que es, de nuevo, una compilación cruzada. </div> <br/> <img width="65%" src="https://hackmd.io/_uploads/BkEXCarqa.png" style="display: block; margin: auto"></img> <br/> <div style="text-align: justify"> Los siguientes pasos, en los que se fijan las configuraciones a desplegar, y el prefijo de la toolchain, serán idénticos a los de la tarea anterior. Tras la creación del proyecto, será necesario fijar la organización de directorios y la incoporporación de archivos tal como aparece en la siguiente figura: </div> <br/> <img width="45%" src="https://hackmd.io/_uploads/HJ04eArcT.png" style="display: block; margin: auto"></img> <div style="text-align: justify"> Para crear un directorio, bastará con utilizar la opción **New > Folder** del menú contextual del proyecto. Los archivos que forman el proyecto, salvo el `main`, están disponibles en el siguiente enlace [prac0_obdh_uart_23_24_files](https://universidaddealcala-my.sharepoint.com/:u:/r/personal/o_rodriguez_uah_es/Documents/public/prac0_obdh_uart_23_24_files.zip?csf=1&web=1&e=xg8FzA). Para compilar el proyecto es necesario configurar el directorio de búsqueda de los includes seleccionando el menú contextual **Properties** sobre el proyecto tal como se muestra en la siguiente figura: <img width="45%" src="https://hackmd.io/_uploads/HJW_jPLca.png" style="display: block; margin: auto"></img> Dentro de **Properties** tendréis que acceder a los *Settings* de *C/C++ Build* y configurar los *include paths* del *Cross GCC Compiler* <img width="85%" src="https://hackmd.io/_uploads/rJ5RiPLc6.png" style="display: block; margin: auto"></img> Añadiendo un nuevo *path*, se seleccionará empleando el botón *Workspace* un path relativo al directorio del proyecto que os permite exportarlo e importarlo independientemente de dónde esté instalado Eclipse. La siguiente figura muestra cómo os debe quedar el path tras seleccionar el directorio *include* del proyecto desde la opción Workspace <img width="85%" src="https://hackmd.io/_uploads/SJTSsPUc6.png" style="display: block; margin: auto"></img> Una vez configurado el *path* de búsqueda de los archivos de cabecera (*includes*), tendremos que crear el archivo `main.c` en el raiz del proyecto. El archivo `main.c`, que se muestra a continuación, configura la GRLIB-UART del SoC basado en LEON3 para disparar una interrupción (la interrupción externa 2) cada vez que se recibe un byte por la UART. El manejador de la interrupción simplemente lee el byte recibido (leon3_getchar()), sin hacer nada con él, e incrementa un contador de bytes recibidos (`rx_byte_counter`). El bucle final del `main`, por su parte, detecta si se ha producido una interrupción comprobando cualquier cambio en esta variable (`if((byte_counter)!=rx_byte_counter){ `), y responde al cambio enviando un punto '.' por la UART con `printf`, ya que en este procesador la salida estándar está asociada a la UART. ```c= #include "leon3_ev_handling.h" #include "leon3_hw_irqs.h" #include "leon3_uart.h" #include <stdio.h> uint32_t rx_byte_counter = 0; void uart_rx_handler(void) { leon3_getchar(); //Leo el caracter para vaciar el buffer rx_byte_counter++; } int main() { uint8_t byte_counter=0; printf("\nInit UART Example\n"); //Instalar como manejador del trap 0x83 la rutina // que habilita las interrupciones leon3_set_trap_handler(0x83, leon3_trap_handler_enable_irqs); //Instalar el manejador del trap que 0x83 la rutina // que deshabilita las interrupciones leon3_set_trap_handler(0x84, leon3_trap_handler_disable_irqs); //Deshabilitar las interrupciones leon3_sys_call_disable_irqs(); //Enmascarar todas las interrupciones, sólo desenmascaremos aquellas que tenemos manejadas. leon3_mask_all_irqs(); //Instalar la función button_handler como // manejador de usuario de la interrupción de nivel 4 leon3_install_user_hw_irq_handler(2, uart_rx_handler); //Configuro UART para disparar interrupciones al recibir un byte leon3_uart_ctrl_rx_irq_enable(); leon3_uart_ctrl_rx_enable(); //Desenmascarar la interrupción de nivel 2 leon3_unmask_irq(2); //Habilitar las interrupciones leon3_sys_call_enable_irqs(); //Sacamos por los displays un incremento do { //Detecta botón pulsado if((byte_counter)!=rx_byte_counter){ printf("."); //Inicio Sección Crítica entre IRQ 2 handler y main leon3_mask_irq(2); byte_counter=rx_byte_counter; //Fin Sección Crítica entre IRQ 2 handler y main leon3_unmask_irq(2); } } while (1); return 0; } ``` </div> <br/> <div style="text-align: justify"> Una vez que el programa compila sin errores, se podrá ejecutar tanto en el simulador TSIM2, como en la placa Nexsys-A7 utilizando diferentes Configuraciones de Depuración (*Debug Configurations*) sobre el mismo proyecto. Para crear una nueva Configuración de Depuración se utiliza el menú contextual del proyecto (botón derecho sobre el proyecto) tal como aparece en la siguiente figura: </div> <br/> <img width="90%" src="https://hackmd.io/_uploads/ry-pHRr96.png" style="display: block; margin: auto"></img> <br/> <div style="text-align: justify"> El menú nos lleva a la vista de depuración (*Debug*) de Eclipse, y desde allí, podemos crear una nueva Configuración de Depuración Hardwarwe basada en GDB (*GDB Hardware Debugging*) eligiendo la opción del menú contextual (botón derecho) *New Configuration*. </div> <br/> <img width="65%" src="https://hackmd.io/_uploads/rJwaB0S5a.png" style="display: block; margin: auto"></img> <br/> <div style="text-align: justify"> La Configuración de Depuración la vamos a denominar `prac0_obdh_uart_23_24 Debug TSIM2`, tal como aparece en la siguiente figura en la pestaña Main. </div> <br/> <img width="100%" src="https://hackmd.io/_uploads/HJcVKABqT.png" style="display: block; margin: auto"></img> <br/> <div style="text-align: justify"> A continuación, accederemos a la pestaña *Debugger* de la Configuración de Depuración para determinar el comando GDB a utilizar (`sparc-elf-gdb`), y la forma con la que GDB se conecta al *Remote Target* TSIM2. Para esta configuración elegiremos las opciones `JTAG Device = Generig TCP/IP` y *GDB Connection String = localhost:1234*. La siguiente figura muestra estas opciones necesarias para cargar y depurar programas sobre TSIM2. </div> <br/> <img width="100%" src="https://hackmd.io/_uploads/HyWZYAS5p.png" style="display: block; margin: auto"></img> <br/> <div style="text-align: justify"> Antes de pulsar el botón *Debug* para iniciar la depuración, deberemos tener arrancado TSIM2. Para eso abriremos un nuevo terminal y, desde línea de comando, ejecutaremos: </div> ```shell tsim-leon3 ``` <div style="text-align: justify"> La ejecución correcta hará que aparezca la información sobre JTAG y una línea de comandos interna de TSIM2 indicada con tsim>. </div> ![tsim-leon3](https://hackmd.io/_uploads/HkE430Sca.png) <div style="text-align: justify"> Al introducir en la línea interna el comando gdb le indicamos a TSIM2 a que abra un puerto para que GDB se conecte a través de él y pueda descargar y depurar programas. Tal como vemos en la siguiente figura el puerto que abre TSIM2 es 1234. </div> ![tsim2_gdb](https://hackmd.io/_uploads/BkbyCCS96.png) <br/> <div style="text-align: justify"> Ahora ya podemos volver a Eclipse y pulsar el botón *Debug* para iniciar la depuración. </div> <br/> <img width="100%" src="https://hackmd.io/_uploads/HyWZYAS5p.png" style="display: block; margin: auto"></img> <br/> <div style="text-align: justify"> Una vez iniciada la depuración, podemos pulsar teclas dentro de la consola de TSIM2 y veremos como aparecen tantos puntos como teclas pulsadas hasta que la depuración finaliza dado que la versión de evaluación tiene un número de ciclos máximo de ejecución. </div> <br/> <img width="100%" src="https://hackmd.io/_uploads/rJ3Uk1Iq6.png" style="display: block; margin: auto"></img> <br/> ## Tarea 3 a realizar: Configuración de Depuración para Nexys-A7 <div style="text-align: justify"> La siguiente tarea a realizar va a consistir en crear una nueva Configuración de Depuración para **el mismo proyecto **`prac0_obdh_uart_23_24` que nos permite trabajar con la placa Nexys-A7 empleando GRMON3 como herramienta para cargar y depurar programas. Para ello, primero cerraremos TSIM2 con la orden `quit` y nos aseguraremos que la anterior depuración ha terminado (Ctrl +F2 o pulsando en el botón Terminate). </div> <br/> <img width="100%" src="https://hackmd.io/_uploads/ByBOGyLca.png" style="display: block; margin: auto"></img> <br/> <div style="text-align: justify"> Después volveremos a la ventana *Debug Configurations* (Accesible desde el menú *Run* y también desde el botón con el icono de la cucaracha) para crear una nueva Configuración de Depuración para **el mismo proyecto **`prac0_obdh_uart_23_24`. Una vez allí, repetimos un paso que ya dimos anteriormente para crear una nueva Configuración de Depuración Hardware basada en GDB (*GDB Hardware Debugging*) eligiendo la opción del menú contextual (botón derecho) *New Configuration*. </div> <br/> <img width="85%" src="https://hackmd.io/_uploads/rJwaB0S5a.png" style="display: block; margin: auto"></img> <br/> <div style="text-align: justify"> Esta nueva Configuración de Depuración la vamos a denominar `prac0_obdh_uart_23_24 Debug NEXYS A7`, tal como aparece en la siguiente figura. Los cambios con respecto a la anterior `prac0_obdh_uart_23_24 Debug TSIM2`, además de en el nombre, se localizan en la configuración de la pestaña *Debugger*, en la que, si bien determinaremos el mismo comando GDB a utilizar (`sparc-elf-gdb`) y la misma forma con la que GDB se conecta al *Remote Target* con `JTAG Device = Generig TCP/IP`, haremos un cambio en el puerto indicando *GDB Connection String = localhost:2222*. La siguiente figura muestra estas opciones necesarias para cargar y depurar programas sobre la Nexys-A7 a través de GRMON3. </div> <img width="85%" src="https://hackmd.io/_uploads/r1aPNyUc6.png" style="display: block; margin: auto"></img> <br/> <div style="text-align: justify"> Antes de proceder a la depuración, es necesario conectar la placa Nexys-A7 al puerto USB de la computadora, y ejecutar GRMON3 con el siguiente telecomando desde una consola. </div> ```shell grmon -digilent -freq 70 ``` <div style="text-align: justify"> La ejecución correcta de GRMON3 mostrará los distintos IP-Cores que integra el SoC de la Nexys-A7 tal como muestra la siguiente figura: </div> <br/> <img width="100%" src="https://hackmd.io/_uploads/ByU_NRSqp.png" style="display: block; margin: auto"></img> <br/> <div style="text-align: justify"> Dentro de la línea de comandos interna de GRMON3 es necesario calibrar las memorias ddr2 que integra mediante el siguiente comando: ```shell grmon3> ddr2delay scan ``` Lo que provocará el siguiente report de ejecución de la calibración: </div> <br/> <img width="100%" src="https://hackmd.io/_uploads/SyXj_J85p.png" style="display: block; margin: auto"></img> <br/> <div style="text-align: justify"> Tras la calibración deberemos salir de GRMON3 y volver a entrar para que esa calibración se aplique. La salida la haremos con `quit`. ```shell grmon3> quit ``` Y una vez de nuevo en la consola del terminal repetimos el comando anterior para ejecutar de nuevo GRMON3 ```shell grmon -digilent -freq 70 ``` Para terminar, dentro de GRMON3 introducimos el comando gdb para que GRMON3 abra un puerto para que GDB se conecte a través de él y pueda descargar y depurar programas. Tal como vemos en la siguiente figura el puerto que abre GRMON3 es 2222, que es el que habíamos utilizado en la opción *GDB Connection String = localhost:2222* de la Configuración de Depuración. ![GRMON_GDB](https://hackmd.io/_uploads/SkLOqJL9a.png) Si bien ya sería posible depurar el programa, necesitamos una herramienta para transmitir los caracteres a la Nexys-A7 por el puerto serie y monitorizar los que la Nexys-A7 envía. Esta herramienta es Minicom, que ya tenéis instalada en vuestra máquina virtual (y en caso contrario, la podéis instalar con `sudo apt-get install minicom`). Para configurarla adecuadamente basta con que introduzcamos desde un terminal el comando ```shell sudo minicom -s ``` A continuación, con Control+A Z se puede acceder a la página de ayuda: ![Minicom](https://hackmd.io/_uploads/r1P140S5T.png) Y desde ahí podemos utilizar el comando 'O' para configurar Minicom. Específicamente, la configuración que nos interesa es la del *Serial port* que seleccionamos del menú: ![Minicom_Option_O_Buena](https://hackmd.io/_uploads/SJylNAH5T.png) Nos aseguraremos que la configuración de Minicom utiliza como *Serial Device* `/dev/ttyUSB1` (puede ser también `/dev/ttyUSB0 o /dev/ttyUSB2`, es necesario ejecutar en consola el siguiente comando para asegurarnos de cuál es el dispositivo asociado a la UART de la Nexys-A7): ```shell ls /dev ``` Además del *Serial Device*, debemos asegurarnos que la configuración Bps/Par/Bits es 38400 8N1 de la opción E (transmisión a 38400 bits por segundo con 8 bits de datos, sin bit de paridad y con 1 bit de parada), y que en las opciones F y G el control de flujo está deshabilitado en ambas tal como muestra la siguiente figura: ![Minicom_Serial_port_options](https://hackmd.io/_uploads/rkNlNRrqp.png) Finalmente, guardaremos la configuración como configuración por defecto para mantenerla en futuras ejecuciones y nos saldremos de la configuración (Exit) ![Minicom_Save_setup_as_dfl](https://hackmd.io/_uploads/BJm-4CBq6.png) Esto nos devolverá al menú principal, donde seleccionaremos la opción (Q) para salir. ![Minicom](https://hackmd.io/_uploads/r1P140S5T.png) Una vez de nuevo en la consola, ejecutaremos minicom con el siguiente y ya tendremos acceso a la transmisión de caracteres a la Nexys-A7 por el puerto serie y a la monitorización de los que la Nexys-A7 nos envía. ```shell sudo minicom ``` Introduciendo mediante el teclado cualquier tipo de caracteres veremos en Minicom una salida como esta que indica que el programa se ejecuta correctamente: ![Minicom_Tarea2](https://hackmd.io/_uploads/HyVv01I5a.png) ## Tarea 4 a realizar: Proyecto de uso de la GPIO de Nexys-A7 <div style="text-align: justify"> La última tarea de la práctica consiste en realizar un nuevo proyecto eclipse para LEON3 en el que se usará la GPIO de la placa Nexys-A7 mediante la función main que se prorporciona a continuación y los archivos que podéis descargar de [prac0_obdh_gpio_nexys_23_24_files](https://universidaddealcala-my.sharepoint.com/:u:/r/personal/o_rodriguez_uah_es/Documents/public/prac0_obdh_gpio_nexys_23_24_files.zip?csf=1&web=1&e=3L0BzB). La organización que debe tener el proyecto es la de la siguiente figura: ![prac9_obdh_gpio_nexys](https://hackmd.io/_uploads/SJjtJl85p.png) Para completarla se deberá crear una única Configuración para Depuración que emplee, en la opción de *Debugger*, la configuración del *Remote Target* del *GDB Connection String = localhost:2222*, ya que sólo desplegaremos sobre la Nexys-A7, puesto que TSIM2 no es capaz de emular de ninguna manera la GPIO de la Nexys-A7 que se utiliza en este ejemplo. Concretamente, lo que hace el programa es asociar una interrupción al pulsado de cualquiera de los 5 botones centrales de la placa, y mostrar por los displays de 7 segmentos la cuenta de las pulsaciones realizadas. Tendréis que utilizar GRMON3 para conectaros a la placa Nexys-A7, al igual que en último ejercicio del anterior apartado. Podéis utilizar también Minicom ya que el programa envía algunos mensajes a través del puerto serie que podrían seros de utilidad. ```c= #include "leon3_ev_handling.h" #include "leon3_hw_irqs.h" #include "nexys_gpio_drv.h" #include <stdio.h> uint8_t current_led = 0; uint8_t displays7seg_value[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; //Clear displays values void clear_displays7segs_values(void) { uint8_t i; for (i = 0; i < 8; i++) displays7seg_value[i] = 0; } //Define next value for displays void next_displays7segs_values(void) { uint8_t end = 0; uint8_t index = 7; while (!end) { if (displays7seg_value[index] < 9) { displays7seg_value[index]++; end = 1; } else { displays7seg_value[index] = 0; if (0 == index) { clear_displays7segs_values(); end = 1; } else { index--; } } } } void button_handler(void) { current_led++; if (10 == current_led) current_led = 0; next_displays7segs_values(); } int main() { uint8_t i; uint8_t led = 0; uint8_t displays7seg_local_copy[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; printf("\nInit GPIO NEXYS EXAMPLE\n"); nexys_srg_gpio_init_buttons_switches(); nexys_srg_gpio_init_leds_7segs_displays(); //Instalar como manejador del trap 0x83 la rutina // que habilita las interrupciones leon3_set_trap_handler(0x83, leon3_trap_handler_enable_irqs); //Instalar el manejador del trap que 0x83 la rutina // que deshabilita las interrupciones leon3_set_trap_handler(0x84, leon3_trap_handler_disable_irqs); //Deshabilitar las interrupciones leon3_sys_call_disable_irqs(); //Enmascarar todas las interrupciones, sólo desenmascaremos aquellas que tenemos manejadas. leon3_mask_all_irqs(); //Instalar la función button_handler como // manejador de usuario de la interrupción de nivel 4 leon3_install_user_hw_irq_handler(4, button_handler); //Configura los 6 botones para que interrumpan al ser pulsados for (i = 0; i < 6; i++) { nexys_srg_gpio_config_button_irq(i, irq_active_low, irq_edge); nexys_srg_gpio_enable_button_irq(i); } //Enciende el primer LED nexys_srg_gpio_turn_on_led(current_led); //Desenmascarar la interrupción de nivel 4 leon3_unmask_irq(4); //Habilitar las interrupciones leon3_sys_call_enable_irqs(); printf("Pulsa Boton para incrementar cuenta\n"); //Sacamos por los displays un incremento do { int first_digit = 0; //Valor de los displays for (i = 0; i < 8; i++) { if (displays7seg_local_copy[i] != 0) first_digit = 1; if (first_digit) nexys_srg_gpio_set_7seg_digit(i, displays7seg_local_copy[i]); } //Detecta botón pulsado if ((led) != current_led) { nexys_srg_gpio_turn_off_led(led); nexys_srg_gpio_turn_on_led(current_led); printf("."); led = current_led; //Inicio Sección Crítica entre IRQ 4 handler y main leon3_mask_irq(4); for (i = 0; i < 8; i++) { displays7seg_local_copy[i] = displays7seg_value[i]; } //Fin Sección Crítica entre IRQ 4 handler y main leon3_unmask_irq(4); } } while (1); return 0; } ``` </div>