Depurar el Neo6502 por SWD: una Pico W como sonda
Cuando la pantalla sigue negra y el puerto serie calla, queda el puerto de depuración del RP2040. Una Pico W, tres cables y OpenOCD: se lee la memoria de la placa mientras funciona, y hasta se teclea en su lugar.
En el Neo6502 de Olimex, el W65C02S ejecuta los programas, pero el RP2040 hace todo lo demás: vídeo DVI, USB, archivos, sonido. Al poner a punto nuestro fork del firmware, Trinity, la primera herramienta es un terminal por puerto serie. Tiene un límite: supone un firmware en buen estado para hablar. El RP2040 tiene además un puerto de depuración, SWD, por el que una sonda lee y escribe su memoria a través del bus, sin pedirle nada al firmware — pantalla negra o firmware bloqueado incluidos. Este es nuestro banco, los comandos, y lo que permitió zanjar.
1. El banco

SWD1.
GP2, GP3 y una masa.Dos placas, dos cables USB: el Neo6502 está alimentado y conectado a su pantalla como siempre; la Pico W va al PC, que la ve como sonda de depuración. Entre ambas, solo tres cables.
2. La sonda: una Pico W y tres cables
La Pico W lleva debugprobe, el firmware de Raspberry Pi que la convierte en sonda CMSIS-DAP. El cableado, tal como figura en nuestros scripts:
| Pico W (sonda) | Neo6502, conector SWD1 |
|---|---|
GP2 | SWCLK (SWC) |
GP3 | SWDIO (SWD) |
GND | GND |
La placa debe estar alimentada por su lado: la sonda no la alimenta.
3. Conectarse: OpenOCD
OpenOCD habla con la sonda y con el RP2040:
openocd -f interface/cmsis-dap.cfg -c "set USE_CORE 0" -f target/rp2040.cfg \
-c "adapter speed 1000" -c "init"
Una vez conectado, read_memory y write_memory leen y escriben cualquier dirección mientras la placa funciona. Las direcciones de las variables del firmware cambian en cada compilación: nuestros scripts nunca las fijan, las releen en el archivo ELF de la versión grabada.
arm-none-eabi-nm firmware.elf | awk '$3 == "frameCounter" { print "0x" $1 }'
# luego, en OpenOCD:
read_memory 0x2000xxxx 16 1
4. Leer el firmware en marcha: neoswd.sh
neoswd.sh relee en bucle algunos contadores del firmware. El más útil es frameCounter, que el núcleo 1 incrementa al inicio de cada fotograma de vídeo: si sigue subiendo, la señal vive y solo la imagen está mal; si está congelado, el codificador se ha parado. Junto a él: lateTotal, los episodios de líneas entregadas con retraso; stoSectorCount, los sectores movidos por el controlador de almacenamiento; y una muestra de la memoria de vídeo, para distinguir una pantalla vacía de una invisible.
firmware/scripts/neoswd.sh 500 # contadores cada 500 ms
firmware/scripts/neopilot.sh "MODE 1" "DIR" # teclea, luego mide
5. Teclear en lugar del teclado: neopilot.sh
Con la pantalla negra ya no se ve lo que se teclea. neopilot.sh escribe directamente en la cola de teclado del firmware (queue y queueTail): un carácter cada 40 ms, luego Intro. Después mide, varias veces por segundo, los niveles de las FIFO del PIO que alimenta el vídeo, sus indicadores de error, el contador de fotogramas y el número de líneas del último fotograma. Así se repite exactamente la misma secuencia, MODE 1 y luego DIR, de un firmware a otro.
6. La regla: conectar solo el núcleo 0
El RP2040 tiene dos núcleos; en Trinity, el núcleo 1 produce el vídeo. OpenOCD puede conectarse a ambos, pero conectar también el núcleo 1 hace caer el codificador a 15 fotogramas por segundo e inventa una avería que no existe (medido el 25 de septiembre de 2026). De ahí set USE_CORE 0 en todos nuestros comandos: el instrumento no debe tocar el codificador. Otro efecto secundario, visto cuando el núcleo 1 tenía prioridad en el bus: hasta las lecturas SWD fallaban, porque el puerto de depuración comparte ese bus.
7. Lo que la sonda zanjó
Durante la pantalla negra del primer DIR en modo Hercules, la sonda mostró que el contador de fotogramas mantenía sus 60 por segundo, que la memoria de vídeo sí contenía el catálogo, y que lateTotal subía durante la lectura del disco: ni firmware congelado ni pantalla borrada. Esa medida, y las siguientes, desmintieron varias explicaciones una tras otra, hasta la causa real — un cerrojo compartido entre los dos núcleos. Toda la búsqueda se cuenta en Un DIR que apaga la pantalla.
8. Lo que no decimos
La sonda lee lo que el firmware guarda en memoria: los contadores citados existen porque los añadimos a Trinity, y sus nombres son los de nuestro fork, no los del firmware oficial. Los scripts suponen el archivo ELF exacto de la versión grabada. Las patillas del conector
SWD1se identifican por la serigrafía de la placa; aquí solo damos las señales.