Interrupts returning to wrong address

Building your first 6502-based project? We'll help you get started here.
sci4me
Posts: 72
Joined: 08 Oct 2013
Location: /home/sci4me
Contact:

Interrupts returning to wrong address

Post by sci4me »

Hey everyone. So, I recently moved my 65c02 computer from a breadboard to a PCB. As far as I can tell, all the hardware is working as intended. However, there is a strange problem with interrupts. The RTI instruction jumps to the wrong place! I've printed this on the serial port: Expected address was $109F, Actual address was $A0A0. The heck?

First I thought I just had a stack issue. But after a lot of auditing (and even printing the stack pointer to serial...) I concluded that this was not the issue.

Then I thought maybe there's a problem with RAM. I wrote a test program that just writes to every address from $0100 to $01FF and reads the written byte back, and checks that they're identical. This problem never found any memory errors...

At this point I'm totally at a loss. I have started to try to build a little debugging jig (poor-man's logic analyzer basically) but haven't gotten that working with the entire computer yet (but it works with only the CPU lol).

I have attached the schematic. If anyone has any ideas, please do reach out! :)
Attachments
schematic.pdf
(829.58 KiB) Downloaded 159 times
rwiker
Posts: 294
Joined: 03 Mar 2011

Re: Interrupts returning to wrong address

Post by rwiker »

I think the accepted wisdom here is that /WE should be qualified by phi2, but /CS should not be. The way you do it, you squeeze the entire RAM operation into one half of a processor cycle.
sci4me
Posts: 72
Joined: 08 Oct 2013
Location: /home/sci4me
Contact:

Re: Interrupts returning to wrong address

Post by sci4me »

rwiker wrote:
I think the accepted wisdom here is that /WE should be qualified by phi2, but /CS should not be. The way you do it, you squeeze the entire RAM operation into one half of a processor cycle.
That's the other thing I've had in the back of my mind; shouldn't /WE be driven from /RWB?

EDIT: Scratch what I just said; was thinking of /WE for some reason. I'd think that it should be driven the same way as /WE but without the phi2 part?

EDIT2: Actually I don't know what I'm talking about right now lol; my brain just got twisted.
So, /WE should be qualified by phi2 but not /CS? Wouldn't that lead to both the CPU and the RAM trying to drive the bus simultaneously?

EDIT3: Is it wrong to be using PHI2O ("PHI2C") rather than PHI2? i.e. I'm using the output from the CPU rather than from the clock directly.
rwiker
Posts: 294
Joined: 03 Mar 2011

Re: Interrupts returning to wrong address

Post by rwiker »

sci4me wrote:
rwiker wrote:
I think the accepted wisdom here is that /WE should be qualified by phi2, but /CS should not be. The way you do it, you squeeze the entire RAM operation into one half of a processor cycle.
That's the other thing I've had in the back of my mind; shouldn't /WE be driven from /RWB?

EDIT: Scratch what I just said; was thinking of /WE for some reason. I'd think that it should be driven the same way as /WE but without the phi2 part?

EDIT2: Actually I don't know what I'm talking about right now lol; my brain just got twisted.
So, /WE should be qualified by phi2 but not /CS? Wouldn't that lead to both the CPU and the RAM trying to drive the bus simultaneously?

EDIT3: Is it wrong to be using PHI2O ("PHI2C") rather than PHI2? i.e. I'm using the output from the CPU rather than from the clock directly.
I just checked against the "6502 Primer", and it looks like I may be wrong about what should be qualified by phi2; see http://wilsonminesco.com/6502primer/addr_decoding.html
sci4me
Posts: 72
Joined: 08 Oct 2013
Location: /home/sci4me
Contact:

Re: Interrupts returning to wrong address

Post by sci4me »

rwiker wrote:
sci4me wrote:
rwiker wrote:
I think the accepted wisdom here is that /WE should be qualified by phi2, but /CS should not be. The way you do it, you squeeze the entire RAM operation into one half of a processor cycle.
That's the other thing I've had in the back of my mind; shouldn't /WE be driven from /RWB?

EDIT: Scratch what I just said; was thinking of /WE for some reason. I'd think that it should be driven the same way as /WE but without the phi2 part?

EDIT2: Actually I don't know what I'm talking about right now lol; my brain just got twisted.
So, /WE should be qualified by phi2 but not /CS? Wouldn't that lead to both the CPU and the RAM trying to drive the bus simultaneously?

EDIT3: Is it wrong to be using PHI2O ("PHI2C") rather than PHI2? i.e. I'm using the output from the CPU rather than from the clock directly.
I just checked against the "6502 Primer", and it looks like I may be wrong about what should be qualified by phi2; see http://wilsonminesco.com/6502primer/addr_decoding.html
So if I read that right, /CS should be qualified by phi2 right?

Also, I just tried using the phi2 input rather than the phi2 output as the input to the decode logic, but it didn't seem to change anything other than that the actual address changed from $A0A0 to $10A0. Strange...
User avatar
GARTHWILSON
Forum Moderator
Posts: 8773
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: Interrupts returning to wrong address

Post by GARTHWILSON »

There's more than one way it can be done. You just have to make sure you don't write to RAM before the address is valid and stable, otherwise you may write to unintended addresses, even if by the end of the cycle the intended address also gets written to. This is because the address is not guaranteed to be valid and stable before the R/W line goes down. You can either just not select the RAM until phase 2 rises (which will be plenty of time after the address is valid and stable), or, if it's really slow RAM and you need the extra setup time, you can select it directly from the address decoding but keep its WR\ input false (ie, high) until phase 2 rises. SRAM is available in much faster speeds than anything else you'll probably put on the bus anyway though, so you probably don't need the extra time afforded by the second method.

The 6502 does not drive the bus during the phase-2-low period; so you don't have to be concerned with bus contention. Even when the 6502 does a store, the data are only guaranteed to become valid some time (tMDS) after phase 2 rises; so if the RAM is putting out data until phase 2 rises, driving its WR\ input low should end that before the '02 starts driving the data bus. As for hold time after the end of the write, bus capacitance will hold the data for a surprisingly long time when nothing is driving the bus—not just nanoseconds, not just microseconds, but even milliseconds, according to my experiments. (Actually, I tripped across that fact accidentally, and although I observed the milliseconds part, I did not go further to see just how long I could take it.)

I tried looking at your .pdf schematic, and all I get is eight totally blank pages.
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?
sci4me
Posts: 72
Joined: 08 Oct 2013
Location: /home/sci4me
Contact:

Re: Interrupts returning to wrong address

Post by sci4me »

GARTHWILSON wrote:
There's more than one way it can be done. You just have to make sure you don't write to RAM before the address is valid and stable. You can either just not select the RAM until phase 2 rises, or, if it's really slow RAM and you need the extra setup time, you can select it directly from the address decoding but keep its WR\ input false (ie, high) until phase 2 rises. SRAM is available in much faster speeds than anything else you'll probably put on the bus anyway though, so you probably don't need the extra time afforded by the second method.

The 6502 does not drive the bus during the phase-2-low period; so you don't have to be concerned with bus contention. Even when the 6502 does a store, the data are only guaranteed to become valid some time (tMDS) after phase 2 rises; so if the RAM is putting out data until phase 2 rises, driving its WR\ input low should end that before the '02 starts driving the data bus. As for hold time after the end of the write, bus capacitance will hold the data for a surprisingly long time when nothing is driving the bus—not just nanoseconds, not just microseconds, but even milliseconds, according to my experiments. (Actually, I tripped across that fact accidentally, and although I observed the milliseconds part, I did not go further to see just how long I could take it.)

I tried looking at your .pdf schematic, and all I get is eight totally bank pages.
Huh, that's really weird. I'll post pictures of the relevant parts. Also, I am using a 1 MHz crystal oscillator for my clock and the RAM is a CY7C199-35PC. I had this all working on the breadboard so it's confusing me that the PCB version is having this issue now. The fact that interrupts are the only thing having any problem like this suggests to me that it may not actually be that I've made a mistake in the hardware, but I find it hard to believe that at the same time, because I don't see how it could be a software mistake, given that I've been using incredibly simple programs just for testing this specific issue.
Attachments
2020-07-20_16-44.png
2020-07-20_16-42.png
2020-07-20_16-42.png (5 KiB) Viewed 2965 times
User avatar
GARTHWILSON
Forum Moderator
Posts: 8773
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: Interrupts returning to wrong address

Post by GARTHWILSON »

I don't offhand see anything wrong with that. You've got a lot of gate delays there, but if you're running at 1MHz, it should be fine. I did edit my last post above to clarify something, but it probably won't affect your circuit. What's in your interrupt code?
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?
sci4me
Posts: 72
Joined: 08 Oct 2013
Location: /home/sci4me
Contact:

Re: Interrupts returning to wrong address

Post by sci4me »

GARTHWILSON wrote:
I don't offhand see anything wrong with that. You've got a lot of gate delays there, but if you're running at 1MHz, it should be fine. I did edit my last post above to clarify something, but it probably won't affect your circuit. What's in your interrupt code?
So, I've done a number of different tests. The simplest way I can think to demonstrate this issue is simply to have the ISR immediately return (`rti`). Then, just use `brk`. So, what I did was to set an LED before the `brk` and set another one after it. And that program ends up just setting the first LED but not the second.

I've also done various tests like printing to to serial via an ACIA, but, given that that simple example is enough to demonstrate the issue, I don't know how relevant this is.

Note that this issue happens both with software and with hardware interrupts. If I recall correctly it also happens on non-maskable interrupts.
User avatar
BigEd
Posts: 11463
Joined: 11 Dec 2008
Location: England
Contact:

Re: Interrupts returning to wrong address

Post by BigEd »

I'd suggest doing something visible in the ISR too. That'll tell you that you arrived.

Do you already know that you can JSR and RTS? The memory activity will be similar.
sci4me
Posts: 72
Joined: 08 Oct 2013
Location: /home/sci4me
Contact:

Re: Interrupts returning to wrong address

Post by sci4me »

BigEd wrote:
I'd suggest doing something visible in the ISR too. That'll tell you that you arrived.

Do you already know that you can JSR and RTS? The memory activity will be similar.
Ah, I should've been more specific. I actually did also have an LED turn on in the ISR. (Technically I used the 7-segment LEDs built into my computer but, neither here nor there.)

And yes, I have JSR and RTS working.

Also, I actually tried, at the end of the interrupt, just re-enabling interrupts and `jmp`ing back to the correct address (since I happened to know the address for that test...) and that works just fine, unsurprisingly. Furthermore, I have confirmed that the issue appears to be that the wrong address is being written to the stack when the interrupt occurs (by printing the address used by `rti` to the serial port.)
thedrip
Posts: 48
Joined: 02 Oct 2018

Re: Interrupts returning to wrong address

Post by thedrip »

By any chance does anything in your ISR write to the stack?

Do you have an NMI triggering during a regular interrupt?

Shotgunning ideas based on mistakes I made on my machine.
User avatar
GARTHWILSON
Forum Moderator
Posts: 8773
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: Interrupts returning to wrong address

Post by GARTHWILSON »

What do you find if you look a few bytes above and below that return address? Is the correct address in there somewhere? (which would indicate you have something in the ISR that's getting the stack out of balance)
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?
sci4me
Posts: 72
Joined: 08 Oct 2013
Location: /home/sci4me
Contact:

Re: Interrupts returning to wrong address

Post by sci4me »

thedrip wrote:
By any chance does anything in your ISR write to the stack?

Do you have an NMI triggering during a regular interrupt?

Shotgunning ideas based on mistakes I made on my machine.
Technically I do have things that write to the stack in the ISR, but I do know that the pushes are matched with pops correctly.
I'm doubtful that I have an NMI triggering... I haven't explicitly checked for this, but, I have the NMI pin tied high with a pull-up resistor.
GARTHWILSON wrote:
What do you find if you look a few bytes above and below that return address? Is the correct address in there somewhere? (which would indicate you have something in the ISR that's getting the stack out of balance)
Just did a quick test of this, here's what I got:

Code: Select all

01FA: 0A
01FB: E3
01FC: 11
01FD: 31
01FE: A0
01FF: 10
0200: 05
0201: FA
0202: 00
0203: 00
I have kept this testing code as simple as possible; probably under a hundred lines total (most of that is just a few utility procedures for the 7-segment LEDs and the ACIA). I'm pretty convinced that I don't have any silly stack mistake like pushing without popping, etc.; if I do, it's fake news; I've literally even printed out the stack pointer at various points to make sure it was popped appropriately, after calling these 'utility procedures'. Not that it's impossible that I've got a bug in the code somewhere, but I have good reason to doubt it.

This issue is going to be the death of me :lol:

EDIT: Strange; I added some more prints for some more stack values, descending from $01FA. That 31 changed to 71. Assuming that's the flags, uh, well, that's weird...
User avatar
Dr Jefyll
Posts: 3525
Joined: 11 Dec 2009
Location: Ontario, Canada
Contact:

Re: Interrupts returning to wrong address

Post by Dr Jefyll »

Hmmm. Earlier you said the RTI instruction jumps to the wrong place. Just for fun, what happens if you use RTI to jump somewhere specific -- $1234, for example -- by doing this (below)? Maybe the success or failure of this will reveal a clue, or raise a new question. :|

Code: Select all

lda #12
pha
lda #34
pha
php
rti
-- Jeff
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html
Post Reply