fachat wrote:
Michael wrote:
gfoot wrote:
Michael wrote:
Ok. Since you've pretty much dis'ed using a microcontroller, how about using an 8K 74AHCTXL18426 "boot loader" IC in a DIP-14 package (~$1.50)?
I'm afraid I don't know what you mean - yes I'm not keen on using a microcontroller for this, and I'm not sure what 74AHCTXL18426 is, did you mean PIC16F18426, or is it the same thing?
Yeah, it's a PIC microcontroller and it simply takes advantage of a simple novel interface method to appear to the 6502 as a 'smart' phantom ROM of sorts. Using it to copy an image of your boot loader into memory at startup is one of many ways you might use it. I use it to copy a full 64K image from a slow ROM at a nice leisurely 1-MHz rate into RAM on a 64K RAM system before switching to a fast clock.
Good luck on your project...
Quote:
How does the copying work with only 14 pins minus two for power supply, to generate addresses to store data to?
Edit: that's probably exactly what described in my post above when ignoring address lines completely. And using a microcontroller you are more flexible - you can even run a 'shadow ' program to see if data read from IO causes branches and then just stream out the right code branch. Nice!
The microcontroller presents to the 6502 as a smart ROM of sorts. It simply provides LDA <imm>, LDA <abs>, STA <abs>, and JMP <abs> instructions while turning on ROM or RAM during the correct cycle within each instruction.
A hardware analogy might look something like the drawing below where you're setting clock and data switches during each half clock cycle to mimick the microcontroller single-cycle Push() and Pull() functions. I'm working on a demo project.
Attachment:
blind interface #2.png [ 356.42 KiB | Viewed 1756 times ]
Code:
/******************************************************************************
* core 'blind interface' functions *
* */
void uReset() // ****************************************
{ clk(1); // clock = 1 *
res(0); // reset = 0 ~~~~~~~~~~~~~~~~~~~~~~~~~~ *
_delay_us(100); // *
uPull(ram); // (1) *
uPull(ram); // (2) *
res(1); // reset = 1 ~~~~~~~~~~~~~~~~~~~~~~~~~~ *
uPull(ram); // (1) *
uPull(ram); // (2) *
uPull(ram); // (3) *
uPull(ram); // (4) *
uPull(ram); // (5) *
uPush(lo(0x8000)); // address $FFFC (reset vector lo) (6) *
uPush(hi(0x8000)); // address $FFFD (reset vector hi) (7) *
} // ****************************************
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' *
} // ****************************************
void wrRAM(byte data) // ****************************************
{ uPush(0xA9); // lda <imm> *
uPush(data); // " *
uPush(0x8D); // sta <abs> *
uPush(lo(addr)); // " abs address lo *
uPush(hi(addr)); // " abs address hi *
uPull(ram); // " 6502 write op' *
} // ****************************************
byte rdMEM(byte mem) // ****************************************
{ uPush(0x4C); // jmp $8000 reset PC (avoid I/O area) *
uPush(lo(0x8000)); // " abs address lo *
uPush(hi(0x8000)); // " 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' *
} // ****************************************
Simply build off of those core functions (loader, programmer, etc.)...
Code:
/******************************************************************************
* load 64K RAM from 64K 'A' or 'B' half of ROM at 'power-up' or 'reset' at *
* a nice liesurely 1-MHz rate. *
* */
void loader() // ****************************************
{ addr = 0x0000; x15(0); // start address $0000, ROM A15 = 0 *
uReset(); // reset CPU (synchronize micro to cpu) *
do // copy 64K ROM minus 8K I/O area to RAM *
{ wrRAM(rdMEM(rom)); // ROM -> RAM (0000..5FFF & 8000..FFFF) *
if(++addr == 0x6000) // if I/O area ($6000..$7FFF) *
{ addr = 0x8000; x15(1); // skip, ROM A15 = 1 ($8000..$FFFF) *
} // *
} while(addr); // until roll-over to 0 (full 64K range) *
} // ****************************************
Code:
/******************************************************************************
* programming 64K RAM image onto 64K 'A' or 'B' half of the 128K Flash ROM *
* takes about 7 seconds. */
void flash() // ****************************************
{ addr = 0x0000; x15(0); // start address $0000, ROM A15 = 0 *
uReset(); // reset 6502 (synchronize uC to cpu) *
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 *
if(++addr == 0x6000) // if I/O area ($6000..$7FFF) *
{ addr = 0x8000; x15(1); // skip, ROM A15 = 1 ($8000..$FFFF) *
} // *
} while(addr); // until roll-over to 0 (full 64K range) *
} // ****************************************
Code:
/******************************************************************************
* hex file download to RAM (ROM emulator mode, 115200 baud) *
* */
char loadHex() // ****************************************
{ char bytecnt; // hex record length *
char type; // hex record type *
char data; // *
char cksum; // hex record checksum *
char error = 0; // *
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; // *
} // ****************************************