Dr Jefyll wrote:
BigEd wrote:
for some purposes it's worth waiting for a SYNC.
Yes -- for some purposes but not all. And (if I understand you correctly) you're suggesting Gordon's case isn't one that requires waiting for SYNC. I tend to agree, but as I was writing this post I did have one nagging second thought.
I'm tempted to say it simply doesn't matter what the 'C02 is doing -- fetching an opcode or any other activity -- when it gets frozen by the ATmega for a memory update. The only problem that struck me initially is if the 'C02 were actually running code from the region $FF00 through $FFFF and the ATmega updated the very same bytes which the 'C02 was in the process of executing. I can't imagine why Gordon would attempt such a perilous stunt, so I'll rule that out.
Ok... Er ... perilous stunt... Interesting... But yes, I would and have done....
The strategy is to isolate 65C02 (or '816), attach ATmega to the data and address bus, control RW and read/write RAM. As an optimisation on my current boards (both 6502 and 816), I pull A8-15 high with 10K resistors and just drive A0-7. So, from the ATmega I can "see" $FF00 through $FFFF.
(on the '816 board, the upper address bus is held low as the decode GAL senses the BE output signal from te ATmega and uses that to force them low)
This is how I boot the CPU - write ~200 bytes of boot code, write the vectors, detach the ATmega, BE High, Reset High and off it goes. The boot code relocates itself to lower RAM them uses the WAI mechanism to talk to the ATmega to get the rest of the OS loaded.
Communication currently relies on the ATmega polling the Rdy output from the 65C02 or '816. When this goes low (WAI executed), it BE's the '02/'816 attaches itself, reads/writes what's now a 128 byte data + 6 byte 'command' window at $FF00 and off it goes. There are some tiny fragments of code that DO execute in the $FFxx region, but they are vectors that never change once the system has booted. An example is:
Code:
osRdchV: jmp _osRdch ; FFE0: (&0210) Get a byte from current input stream
osAsciV: cmp #$0D ; FFE3: Output a byte to VDU stream expanding
bne osWrchV ; carriage returns (&0D) to LF/CR (&0A,&0D)
osNewlV: lda #$0A ; FFE7: Output a CR/LF to VDU stream
jsr osWrch ; FFE9V: Outputs A followed by CR to VDU stream
osWrcrV: lda #$0D ; FFEC Output a CR to VDU stream
osWrchV: jmp _osWrch ; FFEE: (&020E) Output a character to the VDU stream
And yes, there are issues with the wrong interrupt causing wake from WAI, but I resolved that in the GAL with logic which blocks interrupts when Rdy is low. (And since these are all level IRQs it works well)
What I'm aiming to do is provide another small window for asynchronous data from the ATmega - hence looking for a mechanism for ATmega initiated communications.
I can try the single crystal approach - and in the early days when I pushed it to 16MHz I did just that because I only had one 16Mhz can osc. But felt running that long clock might give issues in the future - although who knew I'd be running it at 16Mhz on a double sided board with pull up resistors on half the address bus... It was amazing enough on stripboard at 16Mhz...
This picture shows it on stripboard:
https://projects.drogon.net/ruby-6502-on-stripboard/You can see the green wire from the can to the can socket for the ATmega.
Quote:
But! Also resident in the $FF00 - $FFFF region are the vectors, and if IRQs, NMIs, RSTs or BRKs are being used then a problem could arise in the event that the ATmega happened to do an update that altered the vector in question after the 'C02 had fetched the vector-low byte but before it had fetched the vector-high byte.
SYNC and VPB are both possible candidates for protecting against this vanishingly unlikely event, but both will be unnecessary if IRQs, NMIs, RSTs and BRKs are not in use when the update occurs. Furthermore, it's worth noting that the problem can't manifest unless the ATmega alters both bytes of the vector in question. If one or the other byte remains the same then the 'C02 will either end up going to the new vector or the old vector but not a fatal mix of the two.
Stuff above $FF90 isn't touched once it's booted and running.
Quote:
BTW, Gordon explained that the ATmega code includes some generous delay before assuming that the RDY signal has been recognized by the 65xx. For this reason -- plus the fact he's using a 'C02 -- I don't think we need to concern ourselves regarding an NMOS CPU's inability to immediately recognize RDY when a write cycle(s) is in progress.
-- Jeff
I think what I'll do now is try the single clock approach on an existing board before I spin a new PCB - I'm thinking mostly in 65C02 land but want the option of swapping in an '816 to the same board, so avoiding Sync, VPB and anything else not common to both CPUs is an advantage, but not the end of the world.
And thanks to all who've contributed - it seems use of the Rdy signal takes you almost into uncharted waters - one of those "seemed like a good idea at the time" things though, and on-paper at least it does look interesting but possibly stopping the clock (on 'modern' CPUs at least) is the way to do it more effectively.
Thanks,
-Gordon