Flash ROM idea - sanity check
- speculatrix
- Posts: 151
- Joined: 03 Apr 2018
- Contact:
Flash ROM idea - sanity check
Hi folks.
I've been getting tired of the little dance I have to do each time I update the ROM code for my homebrew machine, which consusts of:
* Switch off
* Remove the EEPROM and put it in a programmer
* Burn the EEPROM
* Remove from programmer and put back in computer
* Switch on
I have this hair-brained scheme of replacing the EEPROM with flash memory. The CPU board of my (backplane-based) machine would have a small microcontroller that talks to my PC via serial. So when I assemble a new ROM binary on the PC, it would automatically push it to the 6502 machine's flash via the MCU.
I have a proof of concept prototype up and running, but here's the key bit. This prototype has its own RAM. The PC first pushes the binary to the RAM (via the MCU) before instructing the MCU to move the contents into flash. I can't fully remember why I do this as a two-stage process, but let's go with it for now.
I don't want to duplicate RAM on the CPU board, so I figured I'd use the 6502 computer's existing 32KB RAM.
Here's what the process would involve (it's a WDC 65C02):
* The PC contacts the MCU and tells it to go into programming mode
* The MCU asserts the RDY line low to stop the CPU
* The MCU asserts the BE line low to put the CPU's address, data and R/W pins into high-Z
* The PC sends the data to the MCU which writes it to the system RAM
* The MCU writes the data to the flash memory
* The MCU releases the BE line
* The MCU releases the RDY
* The MCU strobes /RST
Am I nuts? What am I missing?
I'd just like to know if this is sane or if there are snags.
I've been getting tired of the little dance I have to do each time I update the ROM code for my homebrew machine, which consusts of:
* Switch off
* Remove the EEPROM and put it in a programmer
* Burn the EEPROM
* Remove from programmer and put back in computer
* Switch on
I have this hair-brained scheme of replacing the EEPROM with flash memory. The CPU board of my (backplane-based) machine would have a small microcontroller that talks to my PC via serial. So when I assemble a new ROM binary on the PC, it would automatically push it to the 6502 machine's flash via the MCU.
I have a proof of concept prototype up and running, but here's the key bit. This prototype has its own RAM. The PC first pushes the binary to the RAM (via the MCU) before instructing the MCU to move the contents into flash. I can't fully remember why I do this as a two-stage process, but let's go with it for now.
I don't want to duplicate RAM on the CPU board, so I figured I'd use the 6502 computer's existing 32KB RAM.
Here's what the process would involve (it's a WDC 65C02):
* The PC contacts the MCU and tells it to go into programming mode
* The MCU asserts the RDY line low to stop the CPU
* The MCU asserts the BE line low to put the CPU's address, data and R/W pins into high-Z
* The PC sends the data to the MCU which writes it to the system RAM
* The MCU writes the data to the flash memory
* The MCU releases the BE line
* The MCU releases the RDY
* The MCU strobes /RST
Am I nuts? What am I missing?
I'd just like to know if this is sane or if there are snags.
It either works or catches fire. Either way is fun.
Zolatron 64 project (on Medium)
Zolatron 64 project (on Medium)
Re: Flash ROM idea - sanity check
speculatrix wrote:
Hi folks.
I've been getting tired of the little dance I have to do each time I update the ROM code for my homebrew machine, which consusts of:
* Switch off
* Remove the EEPROM and put it in a programmer
* Burn the EEPROM
* Remove from programmer and put back in computer
* Switch on
I've been getting tired of the little dance I have to do each time I update the ROM code for my homebrew machine, which consusts of:
* Switch off
* Remove the EEPROM and put it in a programmer
* Burn the EEPROM
* Remove from programmer and put back in computer
* Switch on
- Push and hold Reset Button
- Remove EEPROM from ZIF socket and put it in programmer
- Optional: release reset button
- Burn EEPROM
- Push and hold Reset Button
- Remove EPROM from programmer and put back into board ZIF socket
- Release Reset button
Quote:
I have this hair-brained scheme of replacing the EEPROM with flash memory. The CPU board of my (backplane-based) machine would have a small microcontroller that talks to my PC via serial. So when I assemble a new ROM binary on the PC, it would automatically push it to the 6502 machine's flash via the MCU.
Quote:
I have a proof of concept prototype up and running, but here's the key bit. This prototype has its own RAM. The PC first pushes the binary to the RAM (via the MCU) before instructing the MCU to move the contents into flash. I can't fully remember why I do this as a two-stage process, but let's go with it for now.
I don't want to duplicate RAM on the CPU board, so I figured I'd use the 6502 computer's existing 32KB RAM.
Here's what the process would involve (it's a WDC 65C02):
* The PC contacts the MCU and tells it to go into programming mode
* The MCU asserts the RDY line low to stop the CPU
* The MCU asserts the BE line low to put the CPU's address, data and R/W pins into high-Z
* The PC sends the data to the MCU which writes it to the system RAM
* The MCU writes the data to the flash memory
* The MCU releases the BE line
* The MCU releases the RDY
* The MCU strobes /RST
Am I nuts? What am I missing?
I don't want to duplicate RAM on the CPU board, so I figured I'd use the 6502 computer's existing 32KB RAM.
Here's what the process would involve (it's a WDC 65C02):
* The PC contacts the MCU and tells it to go into programming mode
* The MCU asserts the RDY line low to stop the CPU
* The MCU asserts the BE line low to put the CPU's address, data and R/W pins into high-Z
* The PC sends the data to the MCU which writes it to the system RAM
* The MCU writes the data to the flash memory
* The MCU releases the BE line
* The MCU releases the RDY
* The MCU strobes /RST
Am I nuts? What am I missing?
-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
Re: Flash ROM idea - sanity check
As drogon said, it is not very hard to allow writes to EEPROM from the 6502 side of things - no harder than for Flash I believe - you just need to (a) connect its "WE" pin in the usual way, qualified by the PHI2 clock; (b) be careful with the timing of the writes; and (c) maybe execute write-protect-disable magic sequences. In practice (b) means you really need to run the code from RAM while you're doing this, as while you're writing to it (and for a while afterwards) the EEPROM won't respond correctly to read operations.
If you do it right, you can write pages of 64 bytes to the EEPROM at a very fast speed (just like your EEPROM programmer does) and you can also deal with the EEPROM being "locked" (which means that unintentional writes will be mostly ignored unless you send a prefix code first).
Here is a piece of code I've used for this, to write a single 64-byte page to ROM, including executing the "let me write" magic sequenc to temporarily unlock the EEPROM for this operation. Again note that this code must execute from RAM, though you can have ROM code copy this code to RAM before executing it.
As noted the largest gap between writes here is 18 cycles - you can multiply that by your clock period to check you're not going over the limit for the EEPROM (as if you wait too long, it starts to commit the write and blocks further access for a while). It is quite generous though, e.g. 150us - quite a lot of cycles even at a low clock speed.
waitromidle is a routine that checks whether the EEPROM is currently processing a previous write operation:
While the ROM is busy, it toggles one of the data bits high and low during any read operations you perform, meaning that two reads in a row never produce the same value; this loop just checks for that state and waits for the bit toggling to stop. This can take several milliseconds.
In my system I generally leave the initial boot code in the ROM alone, so writing bad code will never totally brick the system.
Going back to your original idea - I think you could also use a microcontroller for this, especially if it already has full bus access - however the 65C02 is only one control line away from being able to do this itself, so it may be easier to just hook that up.
If you do it right, you can write pages of 64 bytes to the EEPROM at a very fast speed (just like your EEPROM programmer does) and you can also deal with the EEPROM being "locked" (which means that unintentional writes will be mostly ignored unless you send a prefix code first).
Here is a piece of code I've used for this, to write a single 64-byte page to ROM, including executing the "let me write" magic sequenc to temporarily unlock the EEPROM for this operation. Again note that this code must execute from RAM, though you can have ROM code copy this code to RAM before executing it.
Code: Select all
jsr waitromidle
; Execute the temporary unprotect sequence
lda #$aa : sta $d555
lda #$55 : sta $aaaa ; 6 cycles since previous write
lda #$a0 : sta $d555 ; 6 cycles since previous write
; Write all the data
byteloop:
lda (zp_readptr),y : sta (zp_writeptr),y ; 11 or 18 cycles since previous write
iny
dex
bne byteloop
waitromidle is a routine that checks whether the EEPROM is currently processing a previous write operation:
Code: Select all
waitromidle:
pha
poll:
lda $8000 : cmp $8000 : bne poll
pla
rts
In my system I generally leave the initial boot code in the ROM alone, so writing bad code will never totally brick the system.
Going back to your original idea - I think you could also use a microcontroller for this, especially if it already has full bus access - however the 65C02 is only one control line away from being able to do this itself, so it may be easier to just hook that up.
- speculatrix
- Posts: 151
- Joined: 03 Apr 2018
- Contact:
Re: Flash ROM idea - sanity check
gfoot wrote:
however the 65C02 is only one control line away from being able to do this itself, so it may be easier to just hook that up.
BTW, one goal I have for this is to not have to to anything physical. It's not just that I don't want to have to get out of my chair each time I update the ROM code - I want to be able to control the whole operation from the sofa, by SSHing into the PC that assembles and uploads the code.
It either works or catches fire. Either way is fun.
Zolatron 64 project (on Medium)
Zolatron 64 project (on Medium)
Re: Flash ROM idea - sanity check
gfoot wrote:
If you do it right, you can write pages of 64 bytes to the EEPROM at a very fast speed (just like your EEPROM programmer does) and you can also deal with the EEPROM being "locked" (which means that unintentional writes will be mostly ignored unless you send a prefix code first).
However it did protect the EEPROM correctly. At the expense of crashing.
This might not be an issue if everything is running in RAM, but it is an issue if you're running code in EEPROM.
Code: Select all
Project-28/Ruby 6507 Startup
============================
*@
P28: GIBL v6
>REM Poke EEPROM...
>?&1000 = 99
-Gordon
Last edited by drogon on Wed Sep 10, 2025 2:05 pm, edited 1 time in total.
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
Re: Flash ROM idea - sanity check
speculatrix wrote:
gfoot wrote:
however the 65C02 is only one control line away from being able to do this itself, so it may be easier to just hook that up.
BTW, one goal I have for this is to not have to to anything physical. It's not just that I don't want to have to get out of my chair each time I update the ROM code - I want to be able to control the whole operation from the sofa, by SSHing into the PC that assembles and uploads the code.
that's what I need to do in my 6507 system, however that's only because the way I treat the EEPROM - as 8 'banks' of 4K. I do not have 32K of linear address space (it's a 6507 with only 13 address lines and I see 4K of RAM and 4K of ROM at any time).
One way would be like the various AVR (Arduino) systems do it: Have the bootloader "locked" in the upper few (100) bytes and arrange your download into RAM then to EEPROM - while we can't lock regions of the EEPROM like you can on the AVR with careful code, it will work. Just don't ever overwrite the bootstrap/downloader part..
Of-course if/when you need to update the bootloader then you might need to get off the sofa...
-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
Re: Flash ROM idea - sanity check
speculatrix wrote:
Okay, but this is where I get confused (it's not difficult). If the 6502 is writing to the EEPROM, where is the 6502 code to do that (bearing in mind that I'm replacing the entire contents of ROM)? And where's the code that's transferring the ROM code from PC to 6502 machine?
BTW, one goal I have for this is to not have to to anything physical. It's not just that I don't want to have to get out of my chair each time I update the ROM code - I want to be able to control the whole operation from the sofa, by SSHing into the PC that assembles and uploads the code.
BTW, one goal I have for this is to not have to to anything physical. It's not just that I don't want to have to get out of my chair each time I update the ROM code - I want to be able to control the whole operation from the sofa, by SSHing into the PC that assembles and uploads the code.
In the first position EEPROM is just ROM and cannot be modified (so no problems) - normal operations.
In the second place the EEPROM may be written into (with all the related issues) - risky life, but may be also use normally (who write to ROM anyway?)
So leaving the jumper in second place enables for anything (including normal usage).
I have in my "monitor" in ROM command, which copy some code to RAM and then jump there. The code read Serial and decode INTEL HEX lines to either write into RAM or write into buffer in RAM and then copy that buffer to EEPROM with later waiting for the write to finish and read it and compare with the buffer. This way I am able to rewrite any part in EEPROM I wish, eventually rewrite the whole EEPROM part by part (as my buffer allows).
After the HEX sequence ends, the RAM code simply jumps to start of command loop in ROM (I have some jumppoints at the begin of ROM as entrypoints to the Monitor system) - but it would be easy to jump into reset vector instead.
Re: Flash ROM idea - sanity check
You can structure your ROM code such that the booting up, enabling file load portion of the software is stable and always a part of your ROM code. This way you can mess up rest of the ROM program, but always have the ability to load an updated version to correct the previous mistakes. Another word, as long as you have the ability to load and run a file, you don’t have to remove your EEPROM to reprogram it. Load and run file does not necessarily require a ROM; it can also be a state machine, battery backed RAM, lookup table in programmable logic, or a separate file loading MCU.
Bill
Bill
Re: Flash ROM idea - sanity check
Food for thought... NO PROGRAMMER REQUIRED.
I designed an SBC with a 64K RAM IC and a $2 Arduino Nano clone to form the essence of a custom ROM Emulator & Programmer on the SBC. A 128K Flash ROM is used as an "image store". I thought this design might be an economical alternative to the Ben Eater 6502 design since it doesn't require purchasing an EPROM Programmer.
The SBC has two modes of operation; ROM Emulator mode and Run mode.
Programming a Flash ROM (via Nano USB serial @115200 bps and Terminal software on Host PC);
(1) press 'mode' switch to enter 'ROM Emulator' mode (LED = red)
(2) Load one or more hex files via Nano USB serial into 64K RAM
(3) Program 64K 'A' or 'B' portion of Flash ROM from the 64K image in RAM (about 10 seconds)
Running, and testing iterative code changes;
(1) press 'mode' switch to enter 'ROM Emulator' mode (LED = red)
(2) Load one or more hex files via Nano USB serial into 64K RAM
(3) press 'mode' switch to enter 'RUN' mode (LED = green)
The ROM Emulator presents to the 6502 as a phantom ROM of sorts. During power-up or reset the Emulator provides the 6502 with instructions to copy the 64K 'A' or 'B' ROM image into 64K RAM at a nice leisurely 1-MHz rate then it resets the 65C02, starts the 1, 2, 4, or 8 MHz 'run mode' clock, enables the 64K RAM, and disconnects itself from the 6502 bus.
I've had a working prototype for several years and it runs fine at 8 MHz. I've just never finished up the Arduino ROM Emulator code into a sharable form. I can use the prototype area on the SBC to test other address decoder schemes by removing the jumper on the JP1 "HI/LO IO" jumper block and driving the /IO line directly from the new decoder circuitry.
I designed an SBC with a 64K RAM IC and a $2 Arduino Nano clone to form the essence of a custom ROM Emulator & Programmer on the SBC. A 128K Flash ROM is used as an "image store". I thought this design might be an economical alternative to the Ben Eater 6502 design since it doesn't require purchasing an EPROM Programmer.
The SBC has two modes of operation; ROM Emulator mode and Run mode.
Programming a Flash ROM (via Nano USB serial @115200 bps and Terminal software on Host PC);
(1) press 'mode' switch to enter 'ROM Emulator' mode (LED = red)
(2) Load one or more hex files via Nano USB serial into 64K RAM
(3) Program 64K 'A' or 'B' portion of Flash ROM from the 64K image in RAM (about 10 seconds)
Running, and testing iterative code changes;
(1) press 'mode' switch to enter 'ROM Emulator' mode (LED = red)
(2) Load one or more hex files via Nano USB serial into 64K RAM
(3) press 'mode' switch to enter 'RUN' mode (LED = green)
The ROM Emulator presents to the 6502 as a phantom ROM of sorts. During power-up or reset the Emulator provides the 6502 with instructions to copy the 64K 'A' or 'B' ROM image into 64K RAM at a nice leisurely 1-MHz rate then it resets the 65C02, starts the 1, 2, 4, or 8 MHz 'run mode' clock, enables the 64K RAM, and disconnects itself from the 6502 bus.
I've had a working prototype for several years and it runs fine at 8 MHz. I've just never finished up the Arduino ROM Emulator code into a sharable form. I can use the prototype area on the SBC to test other address decoder schemes by removing the jumper on the JP1 "HI/LO IO" jumper block and driving the /IO line directly from the new decoder circuitry.
Last edited by Michael on Thu Feb 05, 2026 6:01 am, edited 18 times in total.
Re: Flash ROM idea - sanity check
Michael wrote:
The ROM Emulator presents to the 6502 as a phantom ROM of sorts. During power-up or reset the Emulator provides the 6502 with instructions to copy the 64K 'A' or 'B' ROM image into 64K RAM at a nice leisurely 1-MHz rate then it resets the 65C02, starts the 1, 2, 4, or 8 MHz 'run mode' clock, enables the 64K RAM, and disconnects itself from the 6502 bus.
Re: Flash ROM idea - sanity check
gilhad wrote:
Michael wrote:
The ROM Emulator presents to the 6502 as a phantom ROM of sorts. During power-up or reset the Emulator provides the 6502 with instructions to copy the 64K 'A' or 'B' ROM image into 64K RAM at a nice leisurely 1-MHz rate then it resets the 65C02, starts the 1, 2, 4, or 8 MHz 'run mode' clock, enables the 64K RAM, and disconnects itself from the 6502 bus.
Code: Select all
******************************************************************************
* low level 'blind interface' single-clock uPush() and uPull() functions *
* allow the Nano to 'push' or 'pull' data to/from the CPU data bus. The *
* uPush() function is used to 'push' data from the Nano to the 6502 over *
* data bus during a 6502 read clock cycle (with RAM and ROM disabled). *
* The uPull() function reads data on the bus during a 6502 read or write *
* clock cycle, usually with either RAM or ROM enabled. *
******************************************************************************/
void uPush(byte data) // ****************************************
{ clk(0); busOut(); // clock lo, Nano bus to 'output' {1}{4} *
PORTB = (PORTB&0xFC)|(data>>6); // set D7..D6 pins (PB1 & PB0) *
PORTD = (PORTD & 3)|(data << 2); // set D5..D0 pins *
clk(1); nop(); nop(); nop(); // clock hi *
} // ****************************************
byte uPull(byte mem) // ****************************************
{ byte data = 0; // *
clk(0); busInp(); // clock lo, Nano bus 'input' (hi-z) *
PORTC &= mem; nop(); nop(); // RAM (PC5) or ROM (PC4) enabled (lo) *
clk(1); nop(); nop(); nop(); // clock hi (plus 187.5-nSecs) *
data = (PIND >> 2); // read/collect D5..D0 bits *
data |= (PINB << 6); // read/collect D7..D6 bits *
PORTC |= 0b00110000; // RAM (PC5) & ROM (PC4) /CE 'off' (hi) *
return data; // *
} // ****************************************Code: Select all
/******************************************************************************
* core 'blind interface' functions *
* */
void uReset() // ****************************************
{ clk(1); // clock = 1 *
res(0); // reset = 0 ~~~~~~~~~~~~~~~~~~~~~~~~~~ *
uPull(nul); // (1) *
uPull(nul); // (2) *
res(1); // reset = 1 ~~~~~~~~~~~~~~~~~~~~~~~~~~ *
uPull(nul); // (1) *
uPull(nul); // (2) *
uPull(nul); // (3) *
uPull(nul); // (4) *
uPull(nul); // (5) *
uPush(lo(0x1000)); // address $FFFC (reset vector lo) (6) *
uPush(hi(0x1000)); // address $FFFD (reset vector hi) (7) *
} // ****************************************
Code: Select all
void wrROM(u16 addr,byte data) // ****************************************
{ uPush(0xA9); // lda <imm> *
uPush(data); // " *
uPush(0x8D); // sta <abs> *
uPush(lo(addr)); // " address lo *
uPush(hi(addr)); // " address hi *
uPull(rom); // " 6502 write op' *
} // ****************************************
byte rdMEM(byte mem) // ****************************************
{ uPush(0x4C); // jmp $1000 reset PC (avoid I/O area) *
uPush(lo(0x1000)); // " abs address lo *
uPush(hi(0x1000)); // " abs address hi *
uPush(0xAD); // lda <abs> *
uPush(lo(addr)); // " abs address lo *
uPush(hi(addr)); // " abs address hi *
return uPull(mem); // " 6502 read op' *
} // ****************************************
void wrRAM(byte data) // ****************************************
{ uPush(0xA9); // lda <imm> *
uPush(data); // " *
uPush(0x8D); // sta <abs> (uses global 'addr' var) *
uPush(lo(addr)); // " abs address lo *
uPush(hi(addr)); // " abs address hi *
uPull(ram); // " 6502 write op' *
} // ****************************************
void wrRAM(u16 addr,byte data) // **********{ overload function }*********
{ uPush(0x4C); // jmp $1000 reset PC (avoid I/O area) *
uPush(lo(0x1000)); // " abs address lo *
uPush(hi(0x1000)); // " abs address hi *
uPush(0xA9); // lda <imm> *
uPush(data); // " *
uPush(0x8D); // sta <abs> *
uPush(lo(addr)); // " address lo *
uPush(hi(addr)); // " address hi *
uPull(ram); // " 6502 write op' *
} // ****************************************
Code: Select all
/******************************************************************************
* load 64K RAM from 64K 'A' or 'B' half of ROM at 'power-up' or 'reset' at *
* a nice leisurely 1-MHz rate. *
* */
void bootload() // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
{ putSer(' '); // ~
run(1); // remove I/O from address space ~
uReset(); // reset 6502 (synchronize uC to cpu) ~
addr = 0x0000; // global 'addr' = $0000 ~
do // copy 64K 'A' or 'B' ROM to RAM ~
{ if((addr & 0x0FFF) == 0) // if 4K sector boundary ~
{ putSer('.'); // indicate progress ~
} // ~
wrRAM(rdMEM(rom)); // ROM -> RAM ($0000..$FFFF) ~
} while(++addr); // until roll-over to $0000 (full 64K) ~
} // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Code: Select all
/******************************************************************************
* program 64K RAM image onto 64K 'A' or 'B' half of the 128K Flash ROM. *
* */
void flash() // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
{ putSer(' '); // ~
uReset(); // reset 6502 (synchronize uC to cpu) ~
run(1); // remove I/O from address space ~
addr = 0x0000; // start address $0000 ~
do // ~
{ if((addr & 0x0FFF) == 0) // if 4K sector boundary ~
{ wrROM(0x5555,0xAA); // erase sector sequence ~
wrROM(0x2AAA,0x55); // " ~
wrROM(0x5555,0x80); // " ~
wrROM(0x5555,0xAA); // " ~
wrROM(0x2AAA,0x55); // " ~
wrROM(addr,0x30); // " ~
_delay_ms(25); // required delay ~
putSer('.'); // indicate progress ~
} // ~
wrROM(0x5555,0xAA); // write byte 'unlock' sequence ~
wrROM(0x2AAA,0x55); // " ~
wrROM(0x5555,0xA0); // " ~
wrROM(addr,rdMEM(ram)); // write byte ~
_delay_us(20); // required write delay ~
} while(++addr); // until roll-over to 0 (full 64K) ~
} // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Code: Select all
/******************************************************************************
* hex file download to RAM (ROM emulator mode, 115200 baud) *
* */
byte loadHex() // ****************************************
{ byte bytecnt; // hex record length *
byte type; // hex record type *
byte data; // *
byte cksum; // hex record checksum *
byte error = 0; // *
uReset(); // reset 6502 (synchronize uP to CPU) *
run(1); // remove I/O from address space *
do // process hex file *
{ do // process hex record *
{ putSer(data = getSer()); // echo & flush <cr> and <lf> chars *
} while(data != ':'); // until we see a ':' record header *
cksum = (bytecnt = getByte()); // get 'byte' (not character) count *
cksum += (data = getByte()); // get address hi *
addr = (data << 8); // " *
cksum += (data = getByte()); // get address lo *
addr += data; // " *
cksum += (type = getByte()); // get record type (0, 1, or 4) *
if(type == 4) // if <extended address> record *
{ cksum += getByte(); // *
cksum += getByte(); // *
} // *
if(type == 0) // if <data> record *
{ while(bytecnt--) // *
{ data = getByte(); // *
cksum += data; // *
wrRAM(data); addr++; // write byte to RAM, bump address *
} // *
} // *
data = getByte(); // get record checksum byte *
if(-data != cksum) error = 1; // test for error *
} while(type != 1); // loop until <end-of-file> record *
return error; // *
} // ****************************************
Hope that helps. Cheerful regards...
Last edited by Michael on Sat Oct 18, 2025 3:57 pm, edited 4 times in total.
Re: Flash ROM idea - sanity check
Wow!
That is really impressive
Thank you very much
That is really impressive
Thank you very much
- speculatrix
- Posts: 151
- Joined: 03 Apr 2018
- Contact:
Re: Flash ROM idea - sanity check
Michael wrote:
a $2 Arduino Nano clone to form the essence of a custom ROM Emulator & Programmer on the SBC.
It either works or catches fire. Either way is fun.
Zolatron 64 project (on Medium)
Zolatron 64 project (on Medium)
Re: Flash ROM idea - sanity check
You're welcome. Should also mention you could go ROM-less and simply use the emulator to load programs via serial and run. Or you can load RAM with a small 6502 boot-loader code from an array placed in the Emulator program. Here's an example where I load an array of Nick Gammon's gPascal image into RAM;
The Emulator can also access the 65C02 peripherals like the VIA (or the SDcard connected to the VIA?). Silly example;
Code: Select all
const uint8_t gPascal[] PROGMEM =
{ 0x4C,0x80,0xDC,0x4C,0x9C,0xDC,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x60, // 8000
0x60,0x60,0x60,0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, // 8010
~~~
}
Code: Select all
/******************************************************************************
* copy 'gPascal' array to 64K RAM @ $8000..$DCB7 & vectors @ $FFFA..$FFFF *
* */
void loadImage() // ****************************************
{ uint16_t ndx = 0; // *
addr = 0x8000; // G-Pascal start address *
uReset(); // reset 6502 (synchronize uC to cpu) *
do // copy G-Pascal array to RAM *
{ wrRAM(pgm_read_word_near(gPascal+ndx));
addr++; ndx++; // *
} while(ndx < sizeof(gPascal)); // *
wrRAM(0xFFFA,lo(0xDC9C)); // NMI vector ($FFFA-$FFFB) = $DC9C *
wrRAM(0xFFFB,hi(0xDC9C)); // *
wrRAM(0xFFFC,lo(0xDC80)); // RES vector ($FFFC-$FFFD) = $DC80 *
wrRAM(0xFFFD,hi(0xDC80)); // *
wrRAM(0xFFFE,lo(0xC74E)); // IRQ vector ($FFFE-$FFFF) = $C74E *
wrRAM(0xFFFF,hi(0xC74E)); // *
} // ****************************************
Code: Select all
/******************************************************************************
* simple VIA Test ~ toggle a Red/Green LED on VIA pins PA7 & PA6 (doesn't *
* require RAM or ROM, just the CPU, the VIA, the 74HC139, and the Nano). *
* */
#define PORT_B 0x6000
#define PORT_A 0x6001
#define DDIR_B 0x6002
#define DDIR_A 0x6003
void testVIA() // ****************************************
{ uReset(); // reset 6502 (synchronize uC to cpu)
run(0); // insert I/O into address space
wrRAM(DDIR_A,0b11111111); // PA7..PA0 outputs
while(1) //
{ uPush(0x4C); // jmp $1000 (avoid PC in I/O area)
uPush(lo(0x1000)); // "
uPush(hi(0x1000)); // "
wrRAM(PORT_A,0b01000001); // green
_delay_ms(500); // delay 500-mS
uPush(0x4C); // jmp $1000 (avoid PC in I/O area)
uPush(lo(0x1000)); // "
uPush(hi(0x1000)); // "
wrRAM(PORT_A,0b10000010); // red
_delay_ms(500); // delay 500-mS
} //
} // ****************************************
Last edited by Michael on Sat Sep 13, 2025 3:14 pm, edited 1 time in total.
Re: Flash ROM idea - sanity check
If you can feed parallel 8-bit data directly to 6502 from your PC, like using a FT245R, then a microcontroller is not needed. Your PC acts as a ROM feeding instructions to 6502. https://www.retrobrewcomputers.org/doku ... og65r2home
Also see this rather long discussion, viewtopic.php?f=4&t=6841
Bill
Also see this rather long discussion, viewtopic.php?f=4&t=6841
Bill