21 de Marzo, 2015

Independiente por fin

He acabado el ensamblador, y revisado el desensamblador porque descubrí varios errores al probar ambas partes a la vez.

La idea es encadenar los dos módulos hasta que el resultado sea el mismo. Por ejemplo, supongamos un binario programa.bin:

$ ./dasm -ds programa.bin > fuente.s
$ ./dasm fuente.s > programa2.bin
$ ./dasm -ds programa2.bin > fuente2.s
$ diff -u fuente.s fuente2.s

En realidad hay que ajustar un poco la salida del desensamblador porque genera ??? cuando no encuentra una instrucción válida del 6502, pero se pueden reemplazar esos casos por un BRK (por ejemplo), que sí es válido para el ensamblador.

Por supuesto todo el desarrollo se hace en una máquina normal, y luego se integra con el sistema operativo del microcomputador para la prueba final.

Esto significa que ya puedo programar mi microcomputador sin la ayuda de un compilador cruzado ejecutándose en otra máquina :). Aquí hay un vídeo de ejemplo (en el que cometo un error; ya he corregido el ensamblador para que detecte esos despistes y muestre un mensaje de error).

Al final el entorno permite el comando list para leer memoria y mostrar el desendamblado (opcionalmente admite una posición de memoria), y as para ensamblar (que nuevamente permite indicar una posición de memoria).

La funcionalidad del ensamblador es bastante básica, pero proporciona lo que podemos esperar de un ensamblador para el 6502 (# para valores inmediatos, $ como prefijo para números hexadecimales, etc).

Además soporta la entrada de cadenas de texto y bytes arbitrarios usando el operador punto, con el ejemplo del vídeo:

as 1b00
 1b00: ."Hello world!", $0a, 0
Ok

Lo que almacena la cadena de texto y los dos bytes que le siguen en la posición de memoria 0x1b00.

Desde luego es bastante rudimentario, porque solo se puede introducir linea a linea y no soporta etiquetas o comentarios, pero creo que es suficiente para poder escribir programas sin ayuda externa ;).

Hay 0 comentarios, anotación clasificada en: avr, arduino.

11 de Marzo, 2015

»Desensamblando código 6502 · Ha sido más sencillo de lo que esperaba y en un par de ratos he implementado un desensamblador de código 6502 para mi microcomputador. El principal motivo es que considero que un microcomputador debe ser programable sin usar herramientas externas (por ahora he estado usando compiladores cruzados, ejecutando en mi portátil con Linux y generando código para el 6502 o nativo del ATmega328p). Ahora se pueden listar los programas, el siguiente paso: ¡un ensamblador!

Hay 0 comentarios, anotación clasificada en: avr, arduino.

9 de Marzo, 2015

»Cargando un pantallazo al estilo de los 80 · Ayer estuve revisando y ajustando la carga de programas vía audio. He creado una llamada al sistema para que los programas ejecutando en la máquina virtual puedan cargar datos en cualquier posición de memoria, de forma que cargar un pantallazo en memoria de vídeo es posible (cuidado, el volumen del vídeo está algo alto). Finalmente he decidido desactivar el vídeo cuando cargan los programas, porque el MCU no tiene suficiente potencia para hacer las dos cosas a la vez ;).

Hay 0 comentarios, anotación clasificada en: avr, arduino.

8 de Marzo, 2015

¡PCB en fabricación!

Hace un par de días pude acabar el diseño del PCB para mi proyecto: DAN64: un microcomputador de 8-bits basado en AVR.

El PCB
Me ha llevado varios días conseguir esta distribución

La verdad es que como primer proyecto es quizás algo ambicioso, y es posible que una vez llegue el PCB el diseño tenga algún fallo fundamental que haga que no funcione como se espera.

En primer lugar mi prototipo está montado en un breadboard, con cables más o menos largos, que hacen que los componentes estén razonablemente separados unos de otros. El PCB contiene el circuito completo en 2.9" x 2", con lo que se pueden dar intereferencias entre componentes que no he podido preveer en el prototipo (algunas sí: el conector del teclado PS/2 tiene un condensador porque generaba una gran cantidad de ruido cuando el teclado no estaba conectado).

Además está la posibilidad de que haya cometido algún error, ya sea al dibujar el esquema de lo que iba montando en el breadborad o porque me he dejado algún detalle que no conozco (a fin de cuentas voy aprendiendo sobre la marcha). La verdad es que KiCad tiene muchas herramientas que te ayudan a detectar fallos (¡y funciona! la primera versión que pensaba que estaba acabada era un total desastre :P), pero no es infalible. Por ejemplo: el footprint que usaba para el conector RCA del vídeo tenía las capas mal y no hubiera podido soldarlo.

Aún con todo lo estoy pasando muy bien con el proyecto. Las placas tardarán aún unas semanas en llegar, precio que hay que pagar por el bajo coste del fabricante; pero es mejor así porque aún tengo que trabajar en el software y si todo sale mal es mejor reducir pérdidas ;).

Actualización: estaba volviendo a soldar el conector PS/2 porque se me había soltado un cable y me he dado cuenta que he cambiado dos pines en el conector PS/2 del PCB :'(. Creo que he metido la pata al mirar el componente, porque en el PCB las cosas se ven desde arriba pero los pines quedan abajo. Espero poder parchear el problema y poder usar las placas, sobretodo para detectar otros posibles problemas, y quizás entonces hacer un nuevo pedido corregido.

Hay 2 comentarios, anotación clasificada en: avr, pcb.

5 de Marzo, 2015

»Programando en C para mi microcomputadora · Estoy dedicando todo mi tiempo libre a KiCad, revisando el esquema y trabajando en el PCB (que con suerte enviaré el prototipo en unos días; y luego esperar a que lo fabriquen y llegue desde USA); pero el fin de semana pasado me peleé con CC65 y conseguí compilar programas en C para mi máquina. Como se podría esperar es más lento que programar en ensamblador, pero además es mucho más lento porque C65 tiene que dar muchas vueltas para poder implementar C con las limitaciones del 6502 ;).

Hay 0 comentarios, anotación clasificada en: avr, arduino.

21 de Febrero, 2015

»Cargando programas · Tras dos semanas de experimentos (y fracasos), por fin he conseguido cargar programas desde audio en mi proyecto. La idea básica es la misma que se utilizaba en los microcomputadores de los años 80 cuando cargaban el software desde cinta, aunque en mi caso sea más parecido a lo que haría un modem. A ver si me animo y escribo una anotación larga explicando cómo funciona el invento ;).

Hay 0 comentarios, anotación clasificada en: avr, arduino.

8 de Febrero, 2015

Hola mundo 6502

Ayer pude ejecutar mi primer programa en código para el 6502 en mi proyecto. El programa lo escribí en ensamblador y se puede compilar con CC65.

; hello.s
; Hello World example for D64 using syscalls
;
.segment "CODE"

.macro  sys         ; syscall
.byte   $02
.endmacro

main:
        tsx         ; save the stack pointer
        lda #>message
        pha
        lda #<message
        pha
        lda #$11    ; put string
        sys
        txs         ; restore the stack

        lda #$00    ; terminate program
        pha         ; also: success (0)
        sys

        jmp *       ; never gets here

message:
        .asciiz "Hello world from 6502!"

Mi máquina virtual que ejecuta código del 6502 tiene una configuración estándar para este tipo de CPU, con el siguiente mapa de memoria:

0x0000 - 0x00ffZero page
0x0100 - 0x01ffStack
0x0200 - 0x19ffVídeo
0x1a00 - 0xffffPrograma

No sé todavía si intentaré ejecutar programas existentes para esta CPU porque normalmente dependerán de un interfaz que cambia con la máquina que lo usa (no es lo mismo un Commodore 64 que un Appel II), pero sí quería ser lo más fiel posible al diseño del 6502 para poder usar compiladores existentes sin mucho trabajo.

Además está claro que los programas que ejecute estarán compilados expresamente para mi máquina, así que puedo añadir una instrucción extra para usar funciones de la máquina virtual implementadas en código nativo del ATmega328p (¡más rápido!).

La instrucción extra es SYS (de syscall, o llamada al sistema) que usa el opcode 0x02 (que es una operación ilegal en el 6502), y el intefaz es sencillo: la función se indica en el acumulador, los parámetros en la pila, y es el origen el responsable de desapilar (porque la función puede devolver valores usando la pila). Más o menos es el mecanismo que usa FreeBSD (Linux usa registros para los parámetros, y el 6502 solo tiene tres, así que no es práctico).

En el hola mundo estoy usando dos funciones: imprimir una cadena de texto acabada en un cero (función 0x11) y terminar programa (función 0x00).

Aún quedan muchas cosas por hacer, pero este era un paso importante en el proyecto. El resultado se puede ver en este vídeo.

Hay 0 comentarios, anotación clasificada en: avr, arduino.

31 de Enero, 2015

»Algunos cálculos · Al generar vídeo compuesto (PAL) hay que procesar una linea (scanline) cada 64 µs, 312.5 lineas por cuadro y 50 cuadros por segundo (en vídeo ¿desentrelazado?, en realidad son 625 lineas cada a 25 Hz). El microcontrolador del Arduino trabaja a 16 MHz, y tenemos unas 52 lineas desde que la sincronización vertical empieza hasta que toca dibujar. La sincronización vertical tiene un coste de unos 10 µs, así que nos quedan unos 2.2464 MHz libres para hacer cosas aparte de dibujar la pantalla. No es mucho, ¿verdad? :(

Hay 0 comentarios, anotación clasificada en: avr, arduino.

27 de Enero, 2015

La arquitectura Harvard

Una de las características de la familia de microcontroladores AVR de Atmel es que siguen una arquitectura Harvard modificada.

Esto es muy importante porque en la arquitectura Harvard los datos y el código se acceden vía buses diferentes. El microcontrolador (MCU de ahora en adelante) lleva incorportadas tres tipos de memoria:

  • Flash: contiene el código ejecutable, y el MCU no puede ejecutar código desde otro tipo de memoria. Esta memoria se puede re-escribir (lentamente), y mantiene su contenido cuando no hay electricidad (esto es: no volátil). Gracias a ser una arquitectura Harvard modificada se puede leer esta memoria como si fueran datos (aunque es algo más lento que la SRAM).
  • SRAM: memoria estática volátil.
  • EEPROM: memoria solo lectura que se puede re-escribir en determinadas condiciones.

Así que un microcontrolador no puede cargar código a memoria externa y ejecutarlo; no ha sido diseñado para trabajar así (ese funcionamiento hace referencia a una arquitectura Von Neumann).

Parece que mucha gente empezando con Arduino no termina de enterarse de este detalle hasta que es algo tarde, y es fuente de bastantes confusiones.

Es por esto que una de las partes de mi proyecto para aprender electrónica necesita implementar un intérprete o máquina virtual para poder ejecutar los programas que pretendo cargar en memoria externa.

¿Qué opciones tengo? Bueno, hay que recordar las características del MCU. Estoy trabajando con un Arduino Uno que viene con un ATmega328p, que nos proporciona:

Flash: 32 KB (programa, datos)
SRAM: 2KB (memoria lectura/escritura)
EEPROM: 1KB (memoria solo lectura)

Y además... con un cristal que nos da una velocidad de 16MHz (se puede llegar a 20MHz, pero no podría seguir usando la comodidad de usar el Arduino como placa de desarrollo), y con muchas cosas que hacer al mismo tiempo :S.

Así que el tema es complicado, no solo por los 2048 bytes de memoria :D, sino porque lo que sea... tiene que entrar en 32KB de código (incluyendo el driver de vídeo, del teclado, etc).

Es cierto que estoy usando 64KB de SRAM externa (por ahora solo como memoria de vídeo, 256x192 en monocromo ya son 6144 bytes que no caben en el Arduino), pero no puedo usarla cuando estoy refrescando la pantalla, así que no es todo lo rápido que se podría esperar.

Llevo un par de semanas dándole vueltas, saltando desde la idea de hacer un intérprete de BASIC a la idea de implementar una máquina virtual sencilla (el 6502 parece sencillo, y existen compiladores cruzados), pero todavía no tengo nada decidido. Lo que no se puede negar es que estoy aprendiendo muchas cosas nuevas ;).

Hay 0 comentarios, anotación clasificada en: avr, arduino.

24 de Enero, 2015

»El teclado funciona · Aún queda bastante trabajo hasta tener un controlador de teclado que haga todo lo que tiene que hacer (en realidad se trata de implementar diferentes capas que normalmente se encuentan en el sistema operativo), pero ya se puede introducir texto con un teclado PS2. En esa demo se siguen usando los componentes que ya estaban "listos" (video generado desde la SRAM externa, etc).

Hay 0 comentarios, anotación clasificada en: avr, arduino.

Entradas antiguas