Intro
Using the serial port for xmodem downloads has made the process of putting executable code into RAM a lot easier and we now have a very friendly environment for developing programs.
Previously I used an Arduino Mega to download programs to ROM for testing. As serial downloads are more convenient I have removed the Arduino Mega from my system. The Mega used to interfere with 6502 initialisation previously so the system is now more reliable. In addition it was messy to have another board attached together with its PC USB connection. However it does mean that I have no method for updating the ROM in situ.
Design
It occured to me that if I can write ROM from the Mega and write RAM from BEN2, I should be able to flash ROM from BEN2. Looking at the Arduino sketch I was using, all I need to do in preparation was set ROM /OE pin high to disable ROM output and set ROM /WE pin low to enable writing. I should then be able to write whatever I wanted to ROM before resetting the values afterwards to /WE=HIGH and /OE=LOW. In fact my circuit used a pull-up resister on /WE and a pull-down resister on /OE so that by default, if the pins were not set the ROM would be in read-only mode.
BEN2's VIA chip provides GPIO capability so I can potentially connect two wires from my VIA chip to ROM/OE and ROM/WE and set them high or low as required. Once that was done I could write data to ROM in the normal way using 6502 STA instruction.
There is one wrinkle I have to remember. When ROM/OE is set low to disable output and allow new values to be input it is not possible to read machine code instructions from the ROM. Consequently the subroutine which copies an executable to ROM must reside in RAM.
Proof of concept
I wrote a simple assembly program which stores a few characters (in fact the string "JOHN") to memory. At first I set the target address as RAM and checked the data was stored properly using the monitor m-command to display a range of memory.
I have five VIA pins not used by the LCD PA0, PA1 (buttons) and PA2, PA3, PA4 (LEDs). I attached wires from PA3 to ROM/WE and PA4 to ROM/OE so that when I set the values high or low I could see on the LEDs their status. In my program I set PA3 low and PA4 high then wrote a string to an address ($9000) in ROM, then reset the pins to enable output and prevent writing.
The program worked fine, I was confident I could write data to ROM.
Attach a program
In fact I also needed to encode the load address for write-ramx, the target_address and data_length in the download binary. A complete binary takes the form:
<\x00\x20><xmodem-3-write-ramx.x=70
bytes><\x00\x10><\x00\x16><via-3-LED-1x.x=22bytes>
In this example the load address for write-ramx is $2000, the target address for LED-1x is $1000 and the length of LED-1x is $0016. I used a shell script to encode the addresses and length and to concatenate write-ramx with the payload program LEX-1x. This package was then transmitted through the serial port to BEN2.
My simple program using the Y register as an index was limited to a maximum "8-bit" program size of 255 bytes. For a full-sized program I went to 6502.org and found a "16-bit" copy subroutine by Bruce Clark called MOVEUP I could use. To use the subroutine I simply needed to specify a source address (the end of the program), a destination address (target_address) and size (data_length).
These were loaded directly from the executable into the program