PINKY-8, the me-too 65C02 SBC that doesn't quite work
-
contrariancomp
- Posts: 6
- Joined: 03 Jul 2017
PINKY-8, the me-too 65C02 SBC that doesn't quite work
Greetings fellow 6502 enthusiasts! Following in what seems like every other 8-bit curmudgeon's footsteps, I've spent the last few months working on a compact, affordable 6502 SBC for my own enjoyment and (hopefully, one day) to serve as the core around which I'll build a wholesome afterschool computing program for local kids. I read and reread Garth Wilson's primer (hereafter The Good Site) and breadboarded out something very close to the basic layout found in his 'potpourri' section. I wrote a few simple routines including a RAM tester and 4-bit KS0066 character LCD driver and drank deeply of the satisfaction of having built a working 8-bit computer. When I discovered that PCB production had become dirt cheap, I designed a densely-packed board and sent the gerbers off to EasyEDA for production. The result was surprisingly professional and, again indulging in the pride that precedes a fall, I open-sourced my layout on GitHub, going with the name 'PINKY-8' so as to permit the tagline, "When ARM's too much, try PINKY." See https://github.com/contrarian-computing/pinky-8
As my goal is to implement support for dual Micro SD 'floppies' and HDMI Video / USB Input via PiGFX (https://github.com/fbergama/pigfx) I opened up CA65 and set to work implementing SPI and a MAX3100 UART driver atop that. When I tested my new ROM, I was surprised by what seemed to be a ton of spurious interrupts from the VIA. I double-checked my VIA initialization code and later pulled IRQ# high on the '02 but my IRQ handler was called again and again. I looked more closely and discovered that I was entering the IRQ handler after certain (generally later-occurring) RTS calls, indicating that the return address on the stack was incorrect, leading the CPU into unaligned/unused memory full of $00, aka BRK. I figured I had unbalanced push/pulls somewhere, audited the code thoroughly and found nothing. I reduced my code to test cases for stack manipulation and the problem disappeared. I added some code back and the behavior returned, ultimately leading to a disturbing revelation: I can make the problem disappear or go away by removing or inserting NOPs between my RESET routine and the rest of the code. Specifically, the problem seems to occur when there is execution of code in the later bytes of page $81 (the second page of ROM). This strongly suggests an address decoding issue of some sort, because if SRAM were somehow enabled (and WE# low) during $81xx reads, it would corrupt the stack in $0100-$01FF. I replaced the SRAM, verified continuity on everything, verified connections from datasheet pinouts, checked for shorts, etc. and failed to uncover any issues with the board. The behavior is consistent for any given ROM, changing only when ROM offsets change.
After 12 hours testing various hypotheses I broke down and ordered a 32 channel logic analyzer. While I'm waiting for it to arrive, would anyone like to spitball as to what shameful mistake I've made? As I said, it's pretty much just The Good Site's basic schematic on a PCB - 16K RAM (from a 32K chip), 32K ROM (128K chip with 4 jumpered banks), decoded with a single 74AC00N. Minty fresh W65C02S and W65C22S from Mouser, running at 2Mhz from an oscillator can. (Full specs on GitHub)
As my goal is to implement support for dual Micro SD 'floppies' and HDMI Video / USB Input via PiGFX (https://github.com/fbergama/pigfx) I opened up CA65 and set to work implementing SPI and a MAX3100 UART driver atop that. When I tested my new ROM, I was surprised by what seemed to be a ton of spurious interrupts from the VIA. I double-checked my VIA initialization code and later pulled IRQ# high on the '02 but my IRQ handler was called again and again. I looked more closely and discovered that I was entering the IRQ handler after certain (generally later-occurring) RTS calls, indicating that the return address on the stack was incorrect, leading the CPU into unaligned/unused memory full of $00, aka BRK. I figured I had unbalanced push/pulls somewhere, audited the code thoroughly and found nothing. I reduced my code to test cases for stack manipulation and the problem disappeared. I added some code back and the behavior returned, ultimately leading to a disturbing revelation: I can make the problem disappear or go away by removing or inserting NOPs between my RESET routine and the rest of the code. Specifically, the problem seems to occur when there is execution of code in the later bytes of page $81 (the second page of ROM). This strongly suggests an address decoding issue of some sort, because if SRAM were somehow enabled (and WE# low) during $81xx reads, it would corrupt the stack in $0100-$01FF. I replaced the SRAM, verified continuity on everything, verified connections from datasheet pinouts, checked for shorts, etc. and failed to uncover any issues with the board. The behavior is consistent for any given ROM, changing only when ROM offsets change.
After 12 hours testing various hypotheses I broke down and ordered a 32 channel logic analyzer. While I'm waiting for it to arrive, would anyone like to spitball as to what shameful mistake I've made? As I said, it's pretty much just The Good Site's basic schematic on a PCB - 16K RAM (from a 32K chip), 32K ROM (128K chip with 4 jumpered banks), decoded with a single 74AC00N. Minty fresh W65C02S and W65C22S from Mouser, running at 2Mhz from an oscillator can. (Full specs on GitHub)
Last edited by contrariancomp on Mon Jul 03, 2017 3:24 am, edited 1 time in total.
- BigDumbDinosaur
- Posts: 9425
- Joined: 28 May 2009
- Location: Midwestern USA (JB Pritzker’s dystopia)
- Contact:
Re: PINKY-8, the me-too 65C02 SBC that doesn't quite work
contrariancomp wrote:
While I'm waiting for it to arrive, would anyone like to spitball as to what shameful mistake I've made? As I said, it's pretty much just The Good Site's basic schematic on a PCB - 16K RAM (from a 32K chip), 32K ROM (128K chip with 4 jumpered banks), decoded with a single 74AC00N. Minty fresh W65C02S and W65C22S from Mouser, running at 2Mhz from an oscillator can. (Full specs on GitHub)
x86? We ain't got no x86. We don't NEED no stinking x86!
Re: PINKY-8, the me-too 65C02 SBC that doesn't quite work
contrariancomp wrote:
"When ARM's too much, try PINKY."
contrariancomp wrote:
I looked more closely and discovered that I was entering the IRQ handler after certain (generally later-occurring) RTS calls, indicating that the return address on the stack was incorrect, leading the CPU into unaligned/unused memory full of $00, aka BRK.
Welcome!
-- Jeff
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html
https://laughtonelectronics.com/Arcana/ ... mmary.html
-
contrariancomp
- Posts: 6
- Joined: 03 Jul 2017
Re: PINKY-8, the me-too 65C02 SBC that doesn't quite work
Gladly! Nice to make your acquaintance, BDD. There's now a JPEG of the schematic in the repo here: https://github.com/contrarian-computing ... -8.sch.jpg
- GARTHWILSON
- Forum Moderator
- Posts: 8773
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Re: PINKY-8, the me-too 65C02 SBC that doesn't quite work
Welcome, and congratulations on the success so far. It sounds like you have a good understanding of how to troubleshoot. I'm glad my 6502 primer was a help.
As you can see, there's no way the SRAM's chip select can go true while the ROM is selected. I was going to say make sure you pay attention to how A14 is used in the memory, since it's a subtle part of the address decoding, but then you posted the link to the schematic while I was writing, and it looks like you took care of it. Make sure you don't leave A15 and 16 on the ROM floating as currently shown. (A small note—monochrome, black lines on white background, seems best for diagrams. BDD is one of our colorblind members. He can correct me if I'm wrong, but I think the light green disappears into the white background for him.) Something I've used to troubleshoot these things is the single-cycler in section 6, the "clock generation" section, the 3rd-to-last diagram on the page.
As you can see, there's no way the SRAM's chip select can go true while the ROM is selected. I was going to say make sure you pay attention to how A14 is used in the memory, since it's a subtle part of the address decoding, but then you posted the link to the schematic while I was writing, and it looks like you took care of it. Make sure you don't leave A15 and 16 on the ROM floating as currently shown. (A small note—monochrome, black lines on white background, seems best for diagrams. BDD is one of our colorblind members. He can correct me if I'm wrong, but I think the light green disappears into the white background for him.) Something I've used to troubleshoot these things is the single-cycler in section 6, the "clock generation" section, the 3rd-to-last diagram on the page.
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?
-
contrariancomp
- Posts: 6
- Joined: 03 Jul 2017
Re: PINKY-8, the me-too 65C02 SBC that doesn't quite work
Thanks, Doc, I'll try to tone down the dad humor
In my desperation I fell back on old debugging-with-no-debugger techniques and peppered the code with print statements (for the character LCD). I noticed the pattern after testing a few revisions. I have yet to directly observe bad addresses on the stack so it's all still supposition. Tonight I'll put together a routine to print addresses off the stack and invoke it just before problematic RTS calls. As I'll have to JSR to that routine I'll print out what was put on the stack for it as well.
Dr Jefyll wrote:
Can you elaborate on what "looked more closely" means? Sounds like you're examining the stack upon entry to the ISR. The last items pushed to stack will be the address of a BRK opcode plus two, and the P register. So, you're examining the previous item pushed to stack?
-
contrariancomp
- Posts: 6
- Joined: 03 Jul 2017
Re: PINKY-8, the me-too 65C02 SBC that doesn't quite work
GARTHWILSON wrote:
Welcome, and congratulations on the success so far. It sounds like you have a good understanding of how to troubleshoot. I'm glad my 6502 primer was a help.
GARTHWILSON wrote:
As you can see, there's no way the SRAM's chip select can go true while the ROM is selected.
GARTHWILSON wrote:
Make sure you don't leave A15 and 16 on the ROM floating as currently shown.
GARTHWILSON wrote:
(A small note—monochrome, black lines on white background, seems best for diagrams. BDD is one of our colorblind members. He can correct me if I'm wrong, but I think the light green disappears into the white background for him.)
GARTHWILSON wrote:
Something I've used to troubleshoot these things is the single-cycler in section 6, the "clock generation" section, the 3rd-to-last diagram on the page.
- BigDumbDinosaur
- Posts: 9425
- Joined: 28 May 2009
- Location: Midwestern USA (JB Pritzker’s dystopia)
- Contact:
Re: PINKY-8, the me-too 65C02 SBC that doesn't quite work
contrariancomp wrote:
Gladly! Nice to make your acquaintance, BDD. There's now a JPEG of the schematic in the repo here: https://github.com/contrarian-computing ... -8.sch.jpg
Some things I noted:
- You have BE, NMI(B), RDY and SO(B) all tied to the same pullup resistor. RDY is a bi-directional pin and should be on its own pullup. If the 65C02 executes a WAI instruction it will drive RDY low, which in turn will drive the others low, causing the MPU to high-Z the buses, think it should service a non-maskable interrupt and set the overflow bit in SR (status register), all at the same time. Just think about how confusing that would be to the MPU, not to mention the poor bloke who's trying to get the contraption working.
Now, you may not have used WAI in your code, but a program error could cause the MPU to encounter $CB and think that it is a WAI instruction opcode. - You have pins 12 and 13 of U2 unconnected, leaving those inputs floating. That is a no-no with CMOS hardware. You should either ground them or pull them up to Vcc.
- Are you sure that USB power source you are using to run your machine has enough nuts for the job?
- A design hint for the future: the first gate in U2 is being used as an inverter. You can delete R1 and instead tie pins 1 and 2 together, thus saving on a part and a little bit of PCB real estate.
- A second design hint for the future: do not use the clock outputs of the MPU. WDC doesn't test the performance of those outputs and in fact, doesn't even state how much they lag the clock input, how hard they drive, or the rise and fall time. All clocking should be derived from your Ø2 oscillator (X1).
Last edited by BigDumbDinosaur on Mon Jul 03, 2017 4:44 am, edited 1 time in total.
x86? We ain't got no x86. We don't NEED no stinking x86!
Re: PINKY-8, the me-too 65C02 SBC that doesn't quite work
Echoing BDD's last point I was having a whole stack of stability problems with my own 1st design that I couldn't figure out for the life of me. Cutting the trace from the MPU's Clock output and driving everything directly from the oscillator can fixed that.
Re: Pull-ups, any WAI instructions will also generate an NMI immediately as it shares the same pull-up
If I'm interpreting this correctly, your address decoding is going to select the RAM whenever the VIA is selected too, any time you write to the VIA you're going to write to the ram too?
Your ROM CE and OE are tied together, you can instead tie CE to ground to save a bunch of time for ROM accesses, looking at the datasheet the CE access time is 70-90ns while OE is 30-40ns though doing so will increase power consumption as the rom will never go into standby mode.
Re: Pull-ups, any WAI instructions will also generate an NMI immediately as it shares the same pull-up
If I'm interpreting this correctly, your address decoding is going to select the RAM whenever the VIA is selected too, any time you write to the VIA you're going to write to the ram too?
Your ROM CE and OE are tied together, you can instead tie CE to ground to save a bunch of time for ROM accesses, looking at the datasheet the CE access time is 70-90ns while OE is 30-40ns though doing so will increase power consumption as the rom will never go into standby mode.
- Attachments
-
- Screen Shot 2017-07-03 at 4.24.38 PM.png (39.28 KiB) Viewed 4935 times
Re: PINKY-8, the me-too 65C02 SBC that doesn't quite work
Welcome contrariancomp!
In your IRQ handling routine, you can inspect the saved processor status as found on the stack and distinguish whether you hit a BRK. You could also perhaps save the top three bytes of the stack somewhere and arrange to display them or inspect them later.
In your IRQ handling routine, you can inspect the saved processor status as found on the stack and distinguish whether you hit a BRK. You could also perhaps save the top three bytes of the stack somewhere and arrange to display them or inspect them later.
- GARTHWILSON
- Forum Moderator
- Posts: 8773
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Re: PINKY-8, the me-too 65C02 SBC that doesn't quite work
LIV2 wrote:
If I'm interpreting this correctly, your address decoding is going to select the RAM whenever the VIA is selected too, any time you write to the VIA you're going to write to the ram too?
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?
-
contrariancomp
- Posts: 6
- Joined: 03 Jul 2017
Re: PINKY-8, the me-too 65C02 SBC that doesn't quite work
Thanks for the tremendous support, guys. I'll go into the gory details below but tl;dr is that your suggestions addressed the issue.
This was an oversight on my part that I'll address in the next revision. Thanks for pointing that out.
I made poor assumptions about the independence of gates on the 74xx00. Remedied it with bodge wires but it wasn't sufficient to fix the stack corruption. Again, thanks for the correction - it'll be in the next PCB revision.
I'm using 10W and 12W Apple iPad chargers as they have high output, low noise, very good regulation and safe construction. Though, for whatever reason, Apple decided that voltage sag is a good thing and made these supplies nominally 5.1V and 5.2V, respectively, dropping to ~5V under load. Conveniently, the sag is linear with respect to current right up to the limit so you can compute load from observed voltages. With the 12W charger, VCC is 4.98V with the logic board, CLCD, MAX 3100 and Raspberry Pi Zero going. I based my selection on this comprehensive lab test of common USB chargers.
Makes sense! I don't know why I didn't do that...perhaps I was worried about additional load on A15?
So this, it turns out, was root of the problem. The best places to cut the traces from the '02's PHI2O to the 74AC00 and 65C22 were under the sockets so I started over on a second board, transferring components from the first. With bodge wires in place to transmit the clock directly from X1, I'm no longer seeing stack corruption and spurious BRKs. PHI2O must be sufficiently out of phase to cause RAMSEL to be low at an inopportune moment. Without an oscilloscope it's hard to dig deeper.
I'm very excited to complete my UART and get some text and graphics going on the Pi! Thanks again everyone who pitched in!
BigDumbDinosaur wrote:
You have BE, NMI(B), RDY and SO(B) all tied to the same pullup resistor. RDY is a bi-directional pin and should be on its own pullup. If the 65C02 executes a WAI instruction it will drive RDY low, which in turn will drive the others low, causing the MPU to high-Z the buses, think it should service a non-maskable interrupt and set the overflow bit in SR (status register), all at the same time. Just think about how confusing that would be to the MPU, not to mention the poor bloke who's trying to get the contraption working.
BigDumbDinosaur wrote:
You have pins 12 and 13 of U2 unconnected, leaving those inputs floating. That is a no-no with CMOS hardware. You should either ground them or pull them up to Vcc.
BigDumbDinosaur wrote:
Are you sure that USB power source you are using to run your machine has enough nuts for the job?
BigDumbDinosaur wrote:
A design hint for the future: the first gate in U2 is being used as an inverter. You can delete R1 and instead tie pins 1 and 2 together, thus saving on a part and a little bit of PCB real estate.
BigDumbDinosaur wrote:
A second design hint for the future: do not use the clock outputs of the MPU. WDC doesn't test the performance of those outputs and in fact, doesn't even state how much they lag the clock input, how hard they drive, or the rise and fall time. All clocking should be derived from your Ø2 oscillator (X1).
I'm very excited to complete my UART and get some text and graphics going on the Pi! Thanks again everyone who pitched in!
- BigDumbDinosaur
- Posts: 9425
- Joined: 28 May 2009
- Location: Midwestern USA (JB Pritzker’s dystopia)
- Contact:
Re: PINKY-8, the me-too 65C02 SBC that doesn't quite work
contrariancomp wrote:
BigDumbDinosaur wrote:
A design hint for the future: the first gate in U2 is being used as an inverter. You can delete R1 and instead tie pins 1 and 2 together, thus saving on a part and a little bit of PCB real estate.
Quote:
BigDumbDinosaur wrote:
A second design hint for the future: do not use the clock outputs of the MPU. WDC doesn't test the performance of those outputs and in fact, doesn't even state how much they lag the clock input, how hard they drive, or the rise and fall time. All clocking should be derived from your Ø2 oscillator (X1).
- Timing Notes:
- Timing measurement points are 50% VDD.
- PHI1O and PHI2O clock delay from PHI2 is no longer specified or tested and WDC recommends using an oscillator for system time base and PHI2 processor input clock.
When Bill Mensch designed the 65C02 he wanted to make sure it could be plugged into a system with an NMOS 6502 and everything would work as expected. Hence the PHI1 and PHI2 outputs were retained from the original 6502 design. SOB, which was something that Chuck Peddle apparently thought might be useful, was also carried over, even though it was almost never used (the Commodore 1541 floppy disk drive made use of SOB, the only example I know about). The result was that up until the 65C02 was converted to a static core it was 100 percent hardware compatible with the 6502 and as long as a program didn't use any undefined opcodes, 100 percent software compatible as well.
When the static core conversion of the 65C02 was made, pin 1 was reassigned from being ground to being the VPB output, which slightly broke hardware compatibility. MLB was assigned to the previously no-connect pin 5 and BE was assigned to the previously no-connect pin 36. I was aware of a few systems in which pins 5 and 36 were used as tie points, since they weren't connected to anything in the NMOS part. Plugging a static core 65C02 into such a system would at best result in no operation. At worst it could damage the 'C02.
Quote:
I'm very excited to complete my UART and get some text and graphics going on the Pi! Thanks again everyone who pitched in!
x86? We ain't got no x86. We don't NEED no stinking x86!
- GARTHWILSON
- Forum Moderator
- Posts: 8773
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Re: PINKY-8, the me-too 65C02 SBC that doesn't quite work
contrariancomp wrote:
BigDumbDinosaur wrote:
You have pins 12 and 13 of U2 unconnected, leaving those inputs floating. That is a no-no with CMOS hardware. You should either ground them or pull them up to Vcc.
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?
-
contrariancomp
- Posts: 6
- Joined: 03 Jul 2017
Re: PINKY-8, the me-too 65C02 SBC that doesn't quite work
BigDumbDinosaur wrote:
Which UART are you using?
It took me a while to get everything working with the PiGFX UART, mostly because I didn't trust my own ability to properly interface with the MAX3100. Characters weren't showing up on the Pi and I couldn't figure out what the problem was by inspecting my code. I decided I needed to get serious and invest in proper hardware development tools, so I bought a 32-channel logic analyzer and proceeded to port the entire Sigrok open-source analysis suite to my Linux distribution of choice, which is Solus. After doing this I got some very nice traces out of the 65C22 and MAX3100 which showed that my SPI routines and the MAX's UART were spot on. Only after spending a week on this did I Google issues with PiGFX and discover, from an archived mailing list discussion, that I was simply using an incompatible version of the the Raspberry Pi's bootloader. Swapped one file on the SD card et voila, everything worked as it should.