Honeywell Aerospace SPI/Parallel eeprom. For Aerospace, Deep Earth, and High Temperature applications and (was) priced accordingly... https://aerospace.honeywell.com/content ... asheet.pdf
(I used to work in the Deep Earth development, making steering robots for oil drills. It gets a bit warm down there; we used to design to operate from -40 to +150C, and were looking at +225C when I left.)
Neil
SPI EEPROM boot for 6502
Re: SPI EEPROM boot for 6502
I see you're all way more creative than I am.
I used a large CPLD in the Micro-PET and part of it boots from an SPI ROM, by copying over the first page of the ROM into 6502 page $ffxx, while keepinh phi2 stopped. After that the SPI interface - incl ROM is available as peripheral to the CPU.
My approach would still be a CPLD to do just that. If you want a smaller one you could generate the lower 8 address bits only and pull the upper 8 bits high using other means.
André
I used a large CPLD in the Micro-PET and part of it boots from an SPI ROM, by copying over the first page of the ROM into 6502 page $ffxx, while keepinh phi2 stopped. After that the SPI interface - incl ROM is available as peripheral to the CPU.
My approach would still be a CPLD to do just that. If you want a smaller one you could generate the lower 8 address bits only and pull the upper 8 bits high using other means.
André
Author of the GeckOS multitasking operating system, the usb65 stack, designer of the Micro-PET and many more 6502 content: http://6502.org/users/andre/
Re: SPI EEPROM boot for 6502
If you want to do away with the address line generation, you could stream out the exact code sequence the CPU requires while booting - completely ignoring the address lines.
However that quickly gets complicated. Stores need to go to parallel RAM. But I don't think you can use zeropage or stack as this would need detection when to allow reading it instead of getting the value from SPI ROM.
Also you cannot use the same SPI ROM to load the second stage boot code from - as it is busy streaming out the initial boot code to the CPU, you would need a second storage medium.
Also, no wait loops are allowed as the executed code is fixed in ROM. - no dynamic second stage boot program storage can be used. You might get away with an SD card but I don't know enough of its protocol. An SD Card actually requires a second SPI core as the first one is busy streaming the initial boot code...
So, would maybe work, in the category 'because I can', but I doubt it would less resources than a small CPLD that counts addresses, and can be even used to hold the second stage boot code.
However that quickly gets complicated. Stores need to go to parallel RAM. But I don't think you can use zeropage or stack as this would need detection when to allow reading it instead of getting the value from SPI ROM.
Also you cannot use the same SPI ROM to load the second stage boot code from - as it is busy streaming out the initial boot code to the CPU, you would need a second storage medium.
Also, no wait loops are allowed as the executed code is fixed in ROM. - no dynamic second stage boot program storage can be used. You might get away with an SD card but I don't know enough of its protocol. An SD Card actually requires a second SPI core as the first one is busy streaming the initial boot code...
So, would maybe work, in the category 'because I can', but I doubt it would less resources than a small CPLD that counts addresses, and can be even used to hold the second stage boot code.
Author of the GeckOS multitasking operating system, the usb65 stack, designer of the Micro-PET and many more 6502 content: http://6502.org/users/andre/
Re: SPI EEPROM boot for 6502
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)?
Good luck on your project...
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!
Author of the GeckOS multitasking operating system, the usb65 stack, designer of the Micro-PET and many more 6502 content: http://6502.org/users/andre/
Re: SPI EEPROM boot for 6502
Same approach as mine, I think: let the processor generate the addresses it wants, but ignore them except when writing.
Though I wouldn't expect to execute loops and branches; no need if all you're doing is loading the ram with a bootloader.
Neil
Though I wouldn't expect to execute loops and branches; no need if all you're doing is loading the ram with a bootloader.
Neil
- Alarm Siren
- Posts: 363
- Joined: 25 Oct 2016
Re: SPI EEPROM boot for 6502
Yes, a CPLD would be "easier" - if you already have the knowledge and infrastructure to program one. Not everyone does, nor is it trivial to get to that position. For this reason I feel like booting from an SPI EEPROM still has a place if it can be made to work. The solution is far from ideal, but it has less "up-front barriers" than a CPLD does.
Want to design a PCB for your project? I strongly recommend KiCad. Its free, its multiplatform, and its easy to learn!
Also, I maintain KiCad libraries of Retro Computing and Arduino components you might find useful.
Also, I maintain KiCad libraries of Retro Computing and Arduino components you might find useful.
Re: SPI EEPROM boot for 6502
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)?
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!
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.
Code: Select all
/******************************************************************************
* 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' *
} // ****************************************
Code: Select all
/******************************************************************************
* 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: Select all
/******************************************************************************
* 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: Select all
/******************************************************************************
* 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; // *
} // ****************************************
Last edited by Michael on Sat Aug 12, 2023 10:20 am, edited 5 times in total.
- GARTHWILSON
- Forum Moderator
- Posts: 8773
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Re: SPI EEPROM boot for 6502
What I did was similar to what barnacle describes. It's described at viewtopic.php?p=91876#p91876 and my next two posts on that page. It's finished and tests fine, but I've been slow to make the system it's made to plug into. I can provide them, and I do show them on the front page of my site, but I have not finished the documentation.
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?