Page 2 of 5
Re: Interrupts returning to wrong address
Posted: Tue Jul 21, 2020 2:00 am
by sci4me
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.
-- Jeff
Good idea! To be fair, I think I sort of mis-spoke earlier. That was before I had really inspected the stack values very much. It does appear that the RTI itself isn't the problem, it's that the stack has the wrong values in it.
I just wrote this real quick:
Code: Select all
.macro rti_jmp addr
lda #>addr
pha
lda #<addr
pha
php
rti
.endmacro
And used that in my main loop, instead of `bra`. It works just fine.
So there's one thing ruled out at least.
EDIT: Do interrupts affect the memory timing? i.e. are the write cycles in an interrupt the same as any other write cycle? I'm just thinking, it really seems like the wrong values are being written to RAM by the CPU somehow. Not that I think that the CPU itself is getting the wrong answer, but maybe there's some weird timing/electrical issue that only occurs when the CPU is writing to the stack during an interrupt. *shrugs*
EDIT 2: I just wrote this as a test:
Code: Select all
ldx #0
: txa
sta $0100,x
lda $0100,x
jsr acia_put_hex_byte
lda #10
jsr acia_putc
inx
bne :-
However, surprisingly, this did not work; I had to use the Y register rather than the index to get it to behave as expected:
Code: Select all
ldy #0
: tya
sta $0100,y
lda $0100,y
jsr acia_put_hex_byte
lda #10
jsr acia_putc
iny
bne :-
Am I just being dumb or is this some kind of bug? I will note that the `acia_put_hex_byte` procedure uses the X register to implement a lookup table for converting hex digits to ASCII characters, but it pushes and pops it to and from the stack. (Also, `acia_putc` uses X for a short delay loop.) The fact that this loop fails when using X only when X is pushed and pops tells me that the problem is that any(?) data written to the stack gets corrupted occasionally. Although, it's strange that this issue would _always_ happen on interrupts...
EDIT 3: Everything I said in EDIT 2 was fake news; I thought I was pushing and popping X but I actually wasn't! Oh well. Fixed that anyway. And, what I was testing for gave the correct results: writing and reading back every stack location works fine.
Re: Interrupts returning to wrong address
Posted: Tue Jul 21, 2020 3:15 am
by Dr Jefyll
Oh well. Fixed that anyway. And, what I was testing for gave the correct results: writing and reading back every stack location works fine.
OK, good.
What's next to debug? Best if you can drill down to something SIMPLE that should work but doesn't. Then post the details, including the code.
BTW, does your ISR make use of that priority encoder IC? Maybe (just as a test) you could simplify the ISR so it ignores the encoder.
Re: Interrupts returning to wrong address
Posted: Tue Jul 21, 2020 3:25 am
by sci4me
Oh well. Fixed that anyway. And, what I was testing for gave the correct results: writing and reading back every stack location works fine.
OK, good.
What's next to debug? Best if you can drill down to something SIMPLE that should work but doesn't. Then post the details, including the code.
BTW, does your ISR make use of that priority encoder IC? Maybe (just as a test) you could simplify the ISR so it ignores the encoder.
Well, this is the simplest ISR I can use that demonstrates this problem:
Obviously I'm not printing anything at that point but I'm pretty confident the failure mode is the same; the stack containing the wrong return address. This with a brk will fail in this way.
I haven't been using the priority encoder in this test code. I do have it inserted into the computer right now, but I have (well, just did) tried removing it and just tying the IRQ line high. And even that fails on `brk`! It's wild. But it does seem to suggest to me that the problem is that when the CPU writes to the stack on an interrupt, there's some corruption going on.
Here's most of the current code:
https://pastebin.com/B9ME8Bmt (I can post the rest if anyone's interested).
Also, here's what I'm using to load the code via serial:
https://github.com/sci4me/xboot (just an XMODEM downloader).
EDIT: The stack pointer is definitely correct; it's $FC every time in the ISR, which makes since since it's $FF in my main loop.
Re: Interrupts returning to wrong address
Posted: Tue Jul 21, 2020 8:58 am
by BigEd
> EDIT: Do interrupts affect the memory timing? i.e. are the write cycles in an interrupt the same as any other write cycle? I'm just thinking, it really seems like the wrong values are being written to RAM by the CPU somehow. Not that I think that the CPU itself is getting the wrong answer, but maybe there's some weird timing/electrical issue that only occurs when the CPU is writing to the stack during an interrupt. *shrugs*
It is true that interrupts are the only time the 6502 will do three cycles of back-to-back writes. I would have guessed that if you had a circuit or timing issue then the two back-to-back writes of a JSR would also show it - but maybe not.
Re: Interrupts returning to wrong address
Posted: Tue Jul 21, 2020 9:37 am
by BitWise
Can you post your interrupt code?
Re: Interrupts returning to wrong address
Posted: Tue Jul 21, 2020 11:03 am
by Chromatix
Looking at the circuit diagrams up-thread, I would note that the canonical method of generating /CS, /OE and /WE signals is:
1: /CS for each device should depend only on address lines, /VP, and (for the '816) VDA and VPA. It should not be qualified by Phi2; thus two gates should be removed from the RAM /CS chain.
2: /OE and /WE should be generated as ~(R/W & Phi2) and ~(~(R/W) & Phi2) respectively. They will then produce a pulse on one or the other line on every cycle, during a time interval when the address and /CS signals will all be stable.
At 1MHz the speed of memory devices is not likely to be an issue. Ensuring that relative timing requirements are met, however, is still just as important. If /WE is active at any instant when the address or data lines are not stable, then you can expect incorrect data to be written to the wrong places.
Re: Interrupts returning to wrong address
Posted: Tue Jul 21, 2020 1:06 pm
by sci4me
> EDIT: Do interrupts affect the memory timing? i.e. are the write cycles in an interrupt the same as any other write cycle? I'm just thinking, it really seems like the wrong values are being written to RAM by the CPU somehow. Not that I think that the CPU itself is getting the wrong answer, but maybe there's some weird timing/electrical issue that only occurs when the CPU is writing to the stack during an interrupt. *shrugs*
It is true that interrupts are the only time the 6502 will do three cycles of back-to-back writes. I would have guessed that if you had a circuit or timing issue then the two back-to-back writes of a JSR would also show it - but maybe not.
That's what I was thinking; it seems strange that, if this is an issue with the way I'm driving my RAM chip, it wouldn't show up in places other than interrupts. Not to mention that when I had this _exact same circuit_ with the _exact same chip_ (except I switched from 'LS to 'HC...) on a breadboard, it worked just fine.
Can you post your interrupt code?
I have gone through many iterations of the code, trying to debug this. This is the example I posted earlier:
https://pastebin.com/B9ME8Bmt It includes the ISR which prints out a handful of the values on the stack, to the serial port. If there's something else you're looking for I can sure post that was well.
Looking at the circuit diagrams up-thread, I would note that the canonical method of generating /CS, /OE and /WE signals is:
1: /CS for each device should depend only on address lines, /VP, and (for the '816) VDA and VPA. It should not be qualified by Phi2; thus two gates should be removed from the RAM /CS chain.
2: /OE and /WE should be generated as ~(R/W & Phi2) and ~(~(R/W) & Phi2) respectively. They will then produce a pulse on one or the other line on every cycle, during a time interval when the address and /CS signals will all be stable.
At 1MHz the speed of memory devices is not likely to be an issue. Ensuring that relative timing requirements are met, however, is still just as important. If /WE is active at any instant when the address or data lines are not stable, then you can expect incorrect data to be written to the wrong places.
That's what I had been thinking, but if that were the cause of this problem, wouldn't this interrupt issue have existed on the breadboard version of the computer? I may be mistaken but, I _think_ /WE _and_ /CS shouldn't ever be active when the addr/data isn't stable. /WE may be active before /CS is but that should be fine? Either way, I'm going to try and change the circuit to this after work and see if that changes anything. Maybe I'll get lucky.
Re: Interrupts returning to wrong address
Posted: Tue Jul 21, 2020 1:18 pm
by Dr Jefyll
Not to mention that when I had this _exact same circuit_ with the _exact same chip_ (except I switched from 'LS to 'HC...) on a breadboard, it worked just fine.
Which chip got switched from LS to HC? Just curious.
FWIW, at this point I suspect there's a wiring error, and you're
not dealing with the exact same circuit. Some very strange symptoms are possible... especially when a connection is
absent, resulting in a CMOS input that floats.
-- Jeff
Re: Interrupts returning to wrong address
Posted: Tue Jul 21, 2020 1:22 pm
by sci4me
Not to mention that when I had this _exact same circuit_ with the _exact same chip_ (except I switched from 'LS to 'HC...) on a breadboard, it worked just fine.
Which chip got switched from LS to HC? Just curious.
FWIW, at this point I suspect there's a wiring error, and you're
not dealing with the exact same circuit. Some very strange symptoms are possible... especially when a connection is
absent, resulting in a CMOS input that floats.
-- Jeff
All of the 74-series chips got switched to HC.
And yeah, I definitely have to agree. It has to be some sort of wiring error, but I don't see it showing up in the schematic, which is interesting. I will say, I did forget to tie the unused inputs of the NAND gates and the NOT gates high/low... but I'm not sure that would cause an issue this consistent and specific. Needless to say, I have updated that in the schematic.
Will post back tonight on what happens when I change the /CS, /OE, and /WE signals to the RAM.
Re: Interrupts returning to wrong address
Posted: Tue Jul 21, 2020 2:22 pm
by BitWise
What triggers the ISR?
You don't seem to be saving the A/X/Y of the interrupted code.
It doesn't seem to do anything to resolve the reason for the interrupt.
Re: Interrupts returning to wrong address
Posted: Tue Jul 21, 2020 2:52 pm
by sci4me
What triggers the ISR?
You don't seem to be saving the A/X/Y of the interrupted code.
It doesn't seem to do anything to resolve the reason for the interrupt.
The interrupt is triggered by the `brk` instruction.
I'm not saving A/X/Y in that code just because I didn't care about their values being preserved. Normally I'd just push A/X/Y and pop at the end of the ISR. But since this testing code doesn't really need their values to be preserved, I eliminated the push/pops just to eliminate any potential points of failure. (This code is _only_ for testing/debugging this specific issue.) Not that I think pushing/popping A/X/Y was causing a problem but, you know. I wanted the code to reproduce the issue to be as minimal as possible. I will say though, when I do save and restore A/X/Y, it doesn't seem to change anything.
As for resolving the interrupt source, normally I would read the value from the priority encoder, stored in that D flip-flop and use that to index a jump table, but since this example isn't using any hardware interrupts, only `brk`, it shouldn't matter.
In other code that I have that actually does use this jump-table technique, the resolution works; it jumps to the right handler for the device that caused the interrupt, but the same issue occurs; the return address in the stack appears to be corrupted.
Thank you to everyone for helping so far! I really appreciate it. I just hope we can figure this out

Re: Interrupts returning to wrong address
Posted: Tue Jul 21, 2020 4:09 pm
by Chromatix
One significant difference between 74LS and 74HC is that the former will tend to have disconnected inputs float towards the positive rail, while the latter will float randomly between the rails with a lot of influence from nearby changing signals (they're bounded by the rails only because of ESD protection diodes). It's a consequence of 74LS having a relatively low-impedance input structure compared to 74HC. CMOS logic inputs really don't like being left floating, and it is conceivable that this could affect other gates within the same IC; it will certainly increase power consumption, possibly by a lot.
Re: Interrupts returning to wrong address
Posted: Tue Jul 21, 2020 4:15 pm
by sci4me
One significant difference between 74LS and 74HC is that the former will tend to have disconnected inputs float towards the positive rail, while the latter will float randomly between the rails with a lot of influence from nearby changing signals (they're bounded by the rails only because of ESD protection diodes). It's a consequence of 74LS having a relatively low-impedance input structure compared to 74HC. CMOS logic inputs really don't like being left floating, and it is conceivable that this could affect other gates within the same IC; it will certainly increase power consumption, possibly by a lot.
I will go ahead and tie the unused inputs low (or, high? Which should I choose? Does it matter?) when I get to work on it later today. It definitely was one of the things I missed before getting the board made.
Re: Interrupts returning to wrong address
Posted: Tue Jul 21, 2020 4:25 pm
by Chromatix
For 74HC, it doesn't matter which way you tie them, just so long as they're at one of the rails. For 74LS it's a little more efficient to tie them high.
Re: Interrupts returning to wrong address
Posted: Wed Jul 22, 2020 2:46 am
by BillG
What triggers the ISR?
You don't seem to be saving the A/X/Y of the interrupted code.
It doesn't seem to do anything to resolve the reason for the interrupt.
The interrupt is triggered by the `brk` instruction.
The address pushed by the BRK instruction onto the stack is one greater than the location following the instruction.
Could that be the problem?