Construye tu computadora Mínimum.

Parte 2: Diagrama esquemático.

Por: Oscar Toledo Esteva.       Septiembre de 2018.


Registros de programación

Los microprocesadores contienen celdas de memoria para guardar datos y transferirlos a la memoria temporal o moverlos a otras, estas celdas se llaman registros y pueden almacenar desde un bit hasta 32 bits de datos, el microprocesador de Mínimum tiene 16 registros de 32 bits, R0 hasta R12 es para todo uso, y tres registros R13, R14 y R15 para usos especiales. Los registros de R0 hasta R7 son los mas utilizados por las instrucciones, mientras que los registros R8 hasta R12 requieren ciertas condiciones para su uso. El microprocesador usa la arquitectura de cargar y almacenar (Load and Store) en sus registros, al construir programas con el repertorio de instrucciones es conveniente tener el organigrama de la tarea con los datos, que posteriormente se almacena en la memoria, en el proceso mueve el valor binario al primer operando del registro. Por ejemplo, la instrucción MOVS R1,#04 cubre solo un rango de 8 bits (1 byte) para cubrir la cuarta parte de 32 bits, Por lo tanto 0 4 = 0000 0100 binario, equivale a dos valores hexadecimales como lo indica la tabla de conversión numérica. Se utilizan 16 registros de 32 bits cada uno, donde los registros 0 y 7 son los registros bajos que usan la instrucción MOVS Rd,n, R8 hasta R12 son los registros superiores para uso general, mientras que R13 hasta R15 son registros especiales del microprocesador.

El registro 13 (R13) es de uso exclusivo del Stack Pointer (SP) que guarda la dirección de la pila de memoria, R13 comparte dos funciones indicadoras; la pila principal (Main Stack MSP) y la pila de procesos alternos (Process Stack PSP). En el arranque inicial, el microprocesador utiliza el puntero de la pila de MSP, un dato que el programador coloca en la primera locación de la memoria para indicar en la parte superior de la memoria SRAM en la región 2xxx:xxxx donde el bit 29 siempre es igual a 1, aquí R13 apila solo datos de 32 bits de la parte superior a la inferior de la memoria de trabajo, para salvar el contenido de un registro este se guarda en la pila de memoria que maneja SP, y en automático se pueden almacenar los retornos de subprogramas o subrutinas con la instrucción apropiada, igual que una cadena de datos de los registros, cada locación de memoria ocupada desciende 32 bits el indicador del registro SP. Al meter y sacar datos en la pila de la memoria se utilizan las instrucciones PUSH y POP, otras instrucciones guardan y obtienen el contenido de multiples registros de la pila de memoria. R14 es el Registro de Enlace (LR) que guarda la dirección de retorno de la memoria al regreso de una subrutina o subprograma. R15 es el Program Counter (PC), que guarda y apunta la dirección de la memoria de la próxima instrucción ejecutable.

Los grupos de instrucciones son para:


Instrucciones para guardar o leer en registros de uso general y registros especiales.

Inicialmente las instrucciones usan los registros para fijar sus parametros, el proceso y el resultado del programa. El programa para ensamblar instrucciones tiene un formato para indicar la dirección donde reside el programa, el código máquina, el código de la instrucción o nemónico, además de los comentarios y etiquetas de cada fase del programa escrito por el usuario.

Guarda o mueve un dato en registro:

41 F2 34 20     MOVW R0,#1234   ; R0 es el registro destinario

Guarda o mueve un dato entre registros:

08 46           MOVS R0,R1      ; R1 es el registro fuente que no pierde el
                                ; dato y R0 es el registro destinario.



Programación de la aritmética, desplazamiento o rotación de bits y lógicas.

Hay dos pseudoinstrucciones que maneja el programa ensamblador Familia Toledo, y sirven para guardar datos de 32 bits en registros:


LDR R0,=76543210        ; Este valor se obtiene de una locación
                        ; prefijada de la memoria
ADR R1,=2000:2000       ; Este dato indica la locación directa
                        ; de una memoria del sistema

Registros y locaciones de memoria

En la programación Mínimum solo se puede utilizar el repertorio de instrucciones del microprocesador, cada instrucción binaria de 16 o 32 bits es un código exclusivo para ser leído, codificado y ejecutado por el microprocesador, el conjunto de códigos o claves forman el programa o software de la computadora. Al desarrollar un programa se busca un procedimiento directo o algoritmo, que conduzca a la solución de un problema, este método no es nada nuevo, hace más de 2000 años Euclides observó paso a paso como solucionar problemas con matemáticas, ya en el siglo IX, del nombre del matemático persa Al-Khwarizmi derivó la palabra algoritmo, que suele ser un método definido para desarrollar programas de computadoras, desde un programa que suma dos números enteros hasta rutinas complejas con coma flotante. Un algoritmo se representa mediante un diagrama de flujo u organigrama, para bosquejos visualizados y complicados, el algoritmo se puede expresar en una secuencia de instrucciones llamado código, al escribir el programa se utiliza un lenguaje estructurado de alto nivel -hay docenas de lenguajes de programación- que traduce literalmente del lenguaje cercano al programador las cifras binarias de las claves o códigos máquina que utilizan las instrucciones del microprocesador.



Un programa es un grupo de instrucciones para un proposito, se guarda a partir de una locación de la memoria estática, la dirección la define el usuario que lee y corrige su programa, que al ejecutarse en el microprocesador busca y codifica sus instrucciones para ofrecer el resultado esperado.

Registros de estatus para programas

El listado de instrucciones de un programa se ejecutan de forma secuencial, hasta que una instrucción de salto condicional lo bifurca a otra dirección, una llamada va a una subrutina o se produzca una interrupción. El registro especializado de 32 bits (PSR. Program Status Register) indica el estatus de las operaciones de las instrucciones condicionantes, y el el tipo de operación lo indican las banderas principales N, Z, C y V, con las instrucciones condicionantes. El estatus de las banderas del registro PSR señala cuando el programa salta a otra dirección, al guardar u obtener un dato de forma automática. Para esto, PSR activa los bits binarios de las banderas localizados en los bits 31, 30, 29, 28 y 27, el bit 31 es la bandera N (Negative), subsecuentemente Z (Zero), C (Carry), V (Overflow) y Q (Saturation). Las instrucciones de un programa corren de forma secuencial en una dirección señalada, de acuerdo a la lista del programa, el contador del programa se incrementa a la longitud del código de la instrucción, hasta que la secuencia cambia la ruta del programa. Esto sucede con una instrucción de salto, una ejecución condicional, una llamada a un subprograma y a través de una operación con interruptores, todo tiene que ver con las banderas del registro de estatus, para realizar el enunciado SI-ENTONCES-DE LO CONTRARIO (IF-THEN-ELSE) de la condición booleana, además de exponer que la información verdadera es imprevisible y una información falsa es nula o equivale a cero.


La bandera N es 1 si el resultado es un número negativo, y cero si es un número positivo.
La bandera Z es 1 si el resultado de una cifra es 0, de lo contrario Z = 0.
La bandera C es 1 si ocurre un acarreo en un resultado aritmético, de lo contrario C = 0.
La bandera V es 1 si ocurre un desborde aritmético en la frontera del bit 31, de lo contrario V = 0.
La bandera Q = 1 indica saturación con las instrucciones SSAT o USAT, también indica un desbordamiento de una cifra con DSP.

El registro XPSR tiene una franja de bits para examinar las banderas. Bit 31 = N, bit 30 = Z, bit 29 = C, bit 28 = V y bit 27 = Q. Bit 19:16 son banderas de GE (Greater-Equal) que indican: igual o mayor que, para instrucciones DSP (Digital Signal Processing), bit 8:0 indica con número hexadecimal mas de 256 errores de programación, que pueden ocurrir al realizar programas con interruptor. Es necesario crear un programa depurador que con la ayuda de los registros que muestra las banderas condicionantes, el programador pueda ver cómodamente donde y por qué ocurren errores de programación.

Ejemplo:

MOVS R1,#01     ; R1 = 1
SUBS R1,#01     ; R1 = R1 - 1
                ; R1 = 0
N Z C V
0 1 1 0 ; Z = 1 por el resultado igual a 0

MOVS R1,#02     ; R1 = 2
SUBS R1,#01     ; R1 = R1 - 1
                ; R1 = 1
N Z C V
0 0 1 0 ; Z = 0 por el resultado que no es 0

El resultado de una operación con aritmética, lógica, comparaciones de datos, desplazamiento y rotaciones de bits, activan las banderas de XPSR que deciden las bifurcaciones hacia otra dirección de las instrucciones de los saltos condicionantes. Además, los datos con signo positivo y signo negativo siempre activan las banderas.

Rango de números negativos y positivos, los datos son de 32 bits
con notación hexadecimal.

De 0000:0000 hasta 7FFF:FFFF son datos positivos
De 8000:0000 hasta FFFF:FFFF son datos negativos

Un número negativo lo indica con el bit 31 = 1
Un nùmero positivo lo indica con el bit 31 = 0

Instrucción que activa las banderas

CMP.W R0,#80000000 ; El valor de R0 se compara con 8000:0000.
                   ; El resultado es V=1 que indica un desbordamiento
                   ; de la cifra de 32 bits, y N=1 por el bit 31 = 1 que
                   ; indica que es un número negativo

El siguiente programa es el algoritmo de Euclides para determinar el máximo divisor común (MDC) implementado con las instrucciones de Mínimum, se utilizan dos enteros positivos: El MDC de (A 152) y (B 57) = 19.

Comprobación de A y B después de un número finito de pasos.

A 152 57 MOD = 38    Primera etapa
B 57  38 MOD = 19    Segunda etapa
R 38  19 MOD = 0     Tercera etapa, si final es = 0 el resultado de MDC es 19

Programa para obtener el máximo divisor común de Euclides en Mínimum, solo se usan valores de 8 bits para los enteros positivos escritos con notación hexadecimal.

  MOVS R0,#98     ; A = 152 decimal                        Etapa para fijar
  MOVS R1,#39     ; B = 57 decimal                         parámetros

X CMP R0,R1       ; Compara el valor de A y B              Etapa para continuar
                                                           o terminar

  ITE GT          ; GT (Great Then) condiciona N Z C V     Etapa del bucle
  SUBGT R0,R0,R1  ; Si A es mayor que B: A = A - B         principal
  SUBLT R1,R1,R0  ; Si B es mayor que A: B = B - A
  BNE X           ; Si A = B, finaliza

  MOVW R2,#0100   ; R2 = 00000100 dato de 16 bits en R2   Etapa final
  MOVT R2,#2001   ; R2 = 20010100 locación de la memoria (32 bits)
  STR R0,[R2]     ; El resultado se almacena en la
                  ; dirección de R2

        Resultado: registro 0 = 13 = 19 decimal
                   registro 1 = 0
                   registro de estatus XPSR N=0 No hubo número negativo
                                            Z=1 Hubo cero
                                            C=1 Hubo acarreo
                                            V=0 No hubo desbordamiento

El microprocesador maneja códigos de 16 y 32 bits para las instrucciones, estas consumen tiempo para su ejecución, la mayoría de ellas se ejecutan en un ciclo de reloj, y cada ciclo es un periodo de tiempo de 62.5 nanosegundos con la frecuencia de 16 MHZ. También a cada ciclo de una instrucción se le conoce como ciclo máquina, solo algunas instrucciones requieren mas tiempo para su ejecución, como la instrucción VDIV.F32 S0,S0,S1 que se ejecuta en 14 ciclos del reloj del microprocesador. Con la frecuencia del reloj a 16 MHZ se obtiene el ciclo de trabajo cuando comienza el proceso y la búsqueda de instrucciones, por ejemplo: la instrucción SUBS R1,#1 resta una unidad del valor que contiene el registro 1 y toma un ciclo para ser ejecutada, la instrucción LSLS R1,R1,#13 desplaza 19 veces a la izquierda el valor del registro 1 y toma dos ciclos en ser ejecutada, en cambio la instrucción BNE se ejecuta en 5 ciclos y 3 ciclos si no hay un salto, en algunas instrucciones interviene el conducto de espera de instrucciones (pipeline) que afecta las instrucciones de saltos condicionales, a continuación algunos ejemplos de retardo con su código máquina de 16 bits y 32 bits y la instrucción ensamblada:


        01 21   MOVS R1,#01             ; R1 = 1 se ejecuta en 1 ciclo
        C9 04   LSLS R1,R1,#13          ; Valor desplazado 19 veces a la izquierda
                                        ; para que R1 = 80000 = 524288 decimal
                                        ; sea el contador, se ejecuta en 2 ciclos
 salto  01 39   SUBS R1,#1              ; Resta una unidad al contador,
                                        ; se ejecuta en 1 ciclo
        FD D1   BNE salto               ; Repite la resta hasta que el contador
                                        ; es igual a cero. Se ejecuta en 5 ciclos
                                        ; en cada salto y 2 ciclos si no hay saltos

Resultado = 1 + 2 + (contador - 1) x (1 + 5) + (1 + 2) = 3145728 ciclos

       4F F0 00 51     MOV.W R1,#20000000      ; R1 = 536870912 como contador para
                                               ; obtener los ciclos del retardo
                                               ; se ejecuta en 1 ciclo
salto  01 39           SUBS R1,#1              ; Se ejecuta en 1 ciclo
       FD D1           BNE salto               ; Se ejecuta en 5 ciclos, con
                                               ; un resultado de 3221225470
                                               ; ciclos totales que da un
                                               ; retardo de 3.22 minutos

La cifra FFFFFFFF hexadecimal es el valor màximo de 32 bits que R1 como contador puede manejar, y obtener el máximo retardo con 16 MHZ.

El resultado en ciclos del contador es el mismo si la frecuencia de trabajo es de 16 MHZ o 168 MHZ.

Registros especiales

Para accesar a los registros especiales se utilizan las instrucciones MRS y MSR:

MRS Rg,Re       ; Mueve el dato de un registro especial a un registro
                , de uso general

MSR Re,Rg       ; Mueve el dato de un registro de uso general a un
                ; registro especial

Por ejemplo:

MRS R0,XPSR ; Lectura en R0 del registro especial del estatus del microprocesador

MSR CONTROL, R0 ; Escribe el valor de R0 al registro control

Lenguajes de programación

Un modo de programar el microprocesador es utilizar un programa que maneja lenguaje ensamblador, con resultados ventajosos por su ejecución directa y rápida. Otra alternativa es trabajar con el lenguaje C o C++, por su escritura y el mantenimiento fácil de sus programas, sencillo de implementar en microprocesadores, aunque los compiladores de lenguajes como el C no son amistosos, su compilador puede trasladar el programa a microclaves poco óptimas, con errores de redondeo en cifras con coma flotante y generan programas que ocupan mucho espacio de memoria, además aleja al usuario del lenguaje original del microprocesador, similar a un compilador-traductor del diidxazá al inglés que traduce frases equivocadas o con redundancias de palabras. Solo con el lenguaje ensamblador se logra optimizar las instrucciones del microprocesador, aunque en la práctica puede ser un trabajo laborioso que puede extender el tiempo para concluir el desarrollo del programa.

La mayoría de los programas para los sistemas computarizados se escriben con C, y su compilador traslada la edición del programador a código binario del microprocesador, las literaturas de los fabricantes de chips ponen de ejemplo la programación C para sus productos, dejando relegado el lenguaje ensamblador que maneja directamente las instrucciones del microprocesador, este ultimo se edita con una sintaxis rígida para las etiquetas del programa, bifurcación y la tabla de parámetros de sus instrucciones, principalmente los comentarios, nemónicos y los códigos de cada instrucción, para ilustrar las cifras de las direcciones que se utilizan en el ensamblador y ordenador de códigos.

El lenguaje ensamblador no es fácil de manipular, pero tiene la ventaja de manejar rápido y directo los códigos del microprocesador, en cambio el lenguaje C usa librerías predefinidas para cada microprocesador, que excluye instrucciones especializadas como números de puertas de entradas y salidas, interrupciones para multitareas o el manejo del tiempo de ejecución de un sistema operativo. Aunque manejar directamente los códigos del microprocesador es arduo, suele ser efectivo, mas cuando la velocidad del programa es crítica. Al ejecutar el programa escrito, toda la sintaxis pasa por un filtro del lenguaje para extraer solo las cifras binarias del conjunto de instrucciones que se almacena en la dirección de la memoria de tareas, listo para ser ejecutado por el microprocesador.

Al memorizar gradualmente los nemónicos de las instrucciones el iniciado en lenguaje ensamblador descubre que hay diferentes formas de aplicarlos en los algoritmos clásicos. A la luz de la necesidad de encontrar una mejor solución al procesamiento digital, si realmente se busca rapidez u optimizar un programa, hay que descender hasta el nivel del lenguaje máquina del procesador con el lenguaje ensamblador.

Todos los registros usan las memorias internas del microprocesador, principalmente el registro 13 que siempre indica la dirección de la pila de memoria (Stack Pointer = SP).

Comunicación con Mínimum

Para enlazar Minimum a la computadora anfitrión se utiliza un cable serializado para transmitir y recibir datos del microprocesador, un programa de comunicaciones de creación propia le incluímos un editor, ensamblador y ordenador, además guarda, enlista y ejecuta todas las ordenes que suministra el monitor o debug que se incluye en el microprocesador. Los fabricantes de microprocesadores instalan su firmware exclusivo de comunicación, algunos los nombran bootloader o ISP (In-System-Programming). Particularmente, el microprocesador de Mínimum tiene un depurador con 12 ordenes: para examinar y escribir en la memoria, ejecutar programas del usuario, listar las ordenes incluidas, además de borrar y programar la memoria flash de 1,048,576 bytes, en 12 sectores que comienzan en la dirección 0800:0000 hexadecimal.

Nuestra plataforma con conectores USB y DB9 232C, es el anfitrión de la computadora Minimum y del curso anual de la Familia Toledo "Construye y programa tu computadora". Un software de creación propia comunica ordenes e instrucciones de programas, para depurar, listar, ensamblar instrucciones y ejecutar programas de cualquier tipo; mecatrónica, memoria SD, usos educativos, autoaprendizaje, calculadora científica, comunicación cableada, sensores o grabar una tarea definitiva en la memoria flash del microprocesador.

El microprocesador tiene seis UART (Universal Asynchronous Receiver And Transmitter), para un enlace cableado serializado, en una comunicación con el debug este examina cada UART hasta seleccionar el que está activado con la computadora anfitrión, y desconecta todos los periféricos restantes de comunicación. Se elige un UART y se fija la velocidad de transmisión de la computadora anfitrión a 115200 baudios, y envía la clave 7F hexadecimal para activar Mínimum, cuando el debug del microprocesador sincroniza la velocidad en baudios del UART anfitrión, la computadora responde al anfitrión con la clave 79 hexadecimal como señal de reconocimiento indicando que el enlace está establecido y el microprocesador preparado para recibir programas del anfitrión.

Interfaz serializado RS232C para comunicar al microprocesador con la computadora anfitrión. El switch de botón momentaneo reinicia Mínimum desde una locación prefijada para ejecutar el programa del usuario.

En el depurador WRITE (W) es la orden de escritura, pide al usuario teclear la dirección de la locación donde comienza el volcado de los datos e instrucciones para escribir el programa correspondiente. La orden GO (G) es para ejecutar en una dirección el programa correspondiente. El comienzo de cualquier programa inicia con dos datos de 32 bits, uno para fijar espacios de la memoria (SP) del microprocesador, y en la siguiente el apuntador de la locación donde se van a ejecutar las instrucciones del usuario.

¡Mi laptop solo tiene conector USB y no RS232C! No hay problema, coloque en el circuito impreso un cristal de cuarzo de 8 MHZ y dos condensadores de 20 picofaradios para que el microprocesador sea preciso en 20 PPM (Partes por millones) que requiere el interfaz USB. O también usar un convertidor comercial de USB a UART RS232C.

Circuitos adicionales para mejorar la computadora Minimum.

 

Artículo anterior Artículo anterior Siguiente artículo Siguiente articulo