Full Duplex IRQ driven buffered 6551 driver

Programming the 6502 microprocessor and its relatives in assembly and other languages.
User avatar
floobydust
Posts: 1394
Joined: 05 Mar 2013

Re: Full Duplex IRQ driven buffered 6551 driver

Post by floobydust »

Even more progress, who knew. First, I removed the SEI instructions in the CHIN/CHOUT routines.... has been tested quite a bit without any issues, two more bytes of code saved and a couple clock cycles per routine. I then went back and looked the IRQ service routine. Finally realized I did another dumb thing. I first BIT test the 6551 status register (bit 7 reflected in the n flag) and branch accordingly. I then load the 6551 status register and BIT with RCV and later XMIT masks. If I just load the status register first, bit 7 still gets reflected in the n flag and I don't need to load the status register to test for RCV or XMIT bits later. Saves another 3 bytes of code and 4 clock cycles off the 6551 ISR for all paths, sans initial exit. Updated code:

Code: Select all

INTERUPT	LDA	SIOSTAT	;Get status register, xfer irq bit to n flag (4)
				BPL	REGEXT	;if set, 6551 caused irq,(do not branch) (2/3) (7 clock cycles to exit - take branch)
;
ASYNC		BIT #%00001000	;check receive bit (2)
				BNE RCVCHR	;get received character (2/3) (11 clock cycles to jump to RCV)
				BIT #%00010000	;check xmit bit (2)
				BNE XMTCHR	;send xmit character (2/3) (15 clock cycles to jump to XMIT)
;no bits on means cts went high
				LDA #%00010000 ;cts high mask (2)
IRQEXT		STA STTVAL ;update status value (3) (19 clock cycles to here for CTS fallout)
;
REGEXT		JMP	(IRQRTVEC) ;handle old irq (5)
As of now, the same scenario of sustained transmit at 19.Kbps now takes 295710 clock cycles. With a 1MHz CPU, that's 29.571% of CPU time. The original code took 314910 clock cycles, or 31.491% of the CPU time. A nice savings of 1.92% and 8 bytes of code. :mrgreen:
User avatar
BigDumbDinosaur
Posts: 9428
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: Full Duplex IRQ driven buffered 6551 driver

Post by BigDumbDinosaur »

floobydust wrote:
Even more progress, who knew. First, I removed the SEI instructions in the CHIN/CHOUT routines.... has been tested quite a bit without any issues, two more bytes of code saved and a couple clock cycles per routine.
I told you so. :lol:
Quote:
I then went back and looked the IRQ service routine. Finally realized I did another dumb thing. I first BIT test the 6551 status register (bit 7 reflected in the n flag) and branch accordingly. I then load the 6551 status register and BIT with RCV and later XMIT masks. If I just load the status register first, bit 7 still gets reflected in the n flag and I don't need to load the status register to test for RCV or XMIT bits later. Saves another 3 bytes of code and 4 clock cycles off the 6551 ISR for all paths, sans initial exit. Updated code...
I was wondering if you would spot that. I was going to mention it in my earlier post but decided to let it ride and see if you'd catch it.

When working on time-critical code, especially something like an ISR, I always set it aside after the initial testing and debugging, and then come back to it for a fresh perspective. More often than not, I see something that can be compacted, or perhaps a change in logic that will improve speed. I did that several times with my SCSI driver and manage to both shrink size and execution time. The result is that I got the bus to RAM transfer speed up from about 350KB/sec to about 500KB/sec.

I cover some techniques for improving performance in time-critical code in my 65C816 interrupt article.
x86?  We ain't got no x86.  We don't NEED no stinking x86!
User avatar
floobydust
Posts: 1394
Joined: 05 Mar 2013

Re: Full Duplex IRQ driven buffered 6551 driver

Post by floobydust »

Thanks BDD,

Agreed on going back and re-examining code at a later time. I did that recently on other parts the code and freed up another 50+ bytes and shortened several routines quite a bit. That's part of the challenge (and fun) working in assembly language. There's always another way to skin the cat it seems. Again, appreciate the feedback and insight on this. I need to go back for a refresher on the additional 65C02 opcodes and addressing modes, then start crawling thru code again.
User avatar
BigDumbDinosaur
Posts: 9428
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: Full Duplex IRQ driven buffered 6551 driver

Post by BigDumbDinosaur »

floobydust wrote:
There's always another way to skin the cat it seems.
Especially in assembly language, where there is no inherent structure.
Quote:
I need to go back for a refresher on the additional 65C02 opcodes and addressing modes, then start crawling thru code again.
Be sure to keep the TRB and TSB instructions handy.
x86?  We ain't got no x86.  We don't NEED no stinking x86!
User avatar
barrym95838
Posts: 2056
Joined: 30 Jun 2013
Location: Sacramento, CA, USA

Re: Full Duplex IRQ driven buffered 6551 driver

Post by barrym95838 »

GARTHWILSON wrote:
However the '02, since it probably won't be running a preemptive multitasking OS, probably won't have much use for BRK. I haven't used BRK since I was in school in '82, so I never have the ISR check for it. :D It's usually unnecessary overhead.
That thought occurred to me as well, Garth. If you don't waste any effort snooping for a BRK, and a BRK is actually executed, what would happen? I think that it would probably just be treated as a spurious interrupt, and likely RTI to the following instruction after a short ISR delay (skipping over the BRK post-byte), right? Unless a spurious interrupt causes havoc somehow ...

Mike
User avatar
GARTHWILSON
Forum Moderator
Posts: 8775
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: Full Duplex IRQ driven buffered 6551 driver

Post by GARTHWILSON »

barrym95838 wrote:
GARTHWILSON wrote:
However the '02, since it probably won't be running a preemptive multitasking OS, probably won't have much use for BRK. I haven't used BRK since I was in school in '82, so I never have the ISR check for it. :D It's usually unnecessary overhead.
That thought occurred to me as well, Garth. If you don't waste any effort snooping for a BRK, and a BRK is actually executed, what would happen? I think that it would probably just be treated as a spurious interrupt, and likely RTI to the following instruction after a short ISR delay (skipping over the BRK post-byte), right? Unless a spurious interrupt causes havoc somehow ...
I just don't ever use the BRK instruction, for any reason, so it will never be encountered or executed. If you have code in ROM that someone else wrote and you don't have full info or control on which might have a BRK instruction, it might also have an ISR there that would handle it. I have not looked at for example the C64's ROM listing, but I kind of doubt there are any BRKs there since it was finished up and sold.
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?
User avatar
BigDumbDinosaur
Posts: 9428
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: Full Duplex IRQ driven buffered 6551 driver

Post by BigDumbDinosaur »

GARTHWILSON wrote:
I have not looked at for example the C64's ROM listing, but I kind of doubt there are any BRKs there since it was finished up and sold.
There are no intentional BRK instructions in the C-64's ROM, but the ROM does have code in place to distinguish between an IRQ and a BRK instruction, as well as an indirect vector (IBRK at $0316) that can be used to redirect execution. If undisturbed, that vector sends the 6510 over to the BASIC cold start code, which ultimately puts the user back at the Ready prompt.

Similarly, the C-128 intercepts BRK and jumps through $0316, which starts up the resident machine language monitor.
x86?  We ain't got no x86.  We don't NEED no stinking x86!
Post Reply