6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sun Sep 22, 2024 6:27 pm

All times are UTC




Post new topic Reply to topic  [ 81 posts ]  Go to page Previous  1, 2, 3, 4, 5, 6  Next
Author Message
 Post subject: Re: Multiple interrupts?
PostPosted: Sun Aug 23, 2015 11:21 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8390
Location: Midwestern USA
barrym95838 wrote:
Thanks for looking over that for me, BDD. I edited it after you copied it, changing the rts to php;rti to make the jump table a bit clearer ... a small matter of taste and possibly of future maintainability, but at the expense of one code byte and a few machine cycles. I don't worry about cycle counts until it becomes obvious that I should. In your proposed revision, you are saving at most two machine cycles ... a triviality in all but the most high-strung cases. For some reason, I do care about code footprint size, but that's probably just an idiosyncrasy of mine.

I'm not one to count cycles as a matter of routine, but I do consider the effects of scale. That two cycle savings is trivial in the case of something like a jiffy IRQ, which might occur 100 times per second. However, the savings could become significant when the IRQ rate goes up to thousands per second, which is possible when the IRQs are being caused by an I/O device processing a barrage of data.

For example, if I do a full console screen repaint on my POC V1.1 unit, a minimum of 120 IRQs will occur in a few milliseconds (assuming an 80 × 24 display, and no escape sequences in the output stream). Now, suppose that instead of having the NXP 28L92 UART, which has 16 byte transmit FIFOs, I had the NXP 2692 that I used in POC V1.0. It has no transmit FIFO, which means it will generate an IRQ for each byte transmitted to the display. Suddenly, I'm up to at least 1920 IRQs in a few milliseconds and those two extra cycles caused by the branch taken on each IRQ would translate into 3840 extra cycles consumed during the display repaint. Quite a bit of foreground processing can get done in 3840 cycles.

Quote:
Less than 30 code bytes (plus an appropriately-trimmed jump table) and less than 60 cycles to add the brk signature byte functionality is certainly not a huge cost, but I understand that a different approach may be more desirable in some instances. It could be an overall space win in a larger operating system, due to the space saved in the callers, but the callers would need to have several dozen instances of brk # to make that come to be.

The jump table size is dependent on the number of API functions being implemented, so it's not really something you can do a whole lot about. The performance of the code is something that should be considered, however. Depending on the frequency at which an API call is made, the extra gyrations needed to get the signature could translate to a significant reduction in throughput—it must be understood that all API calls incur that overhead. Again, the best example of where performance could be an issue is output to the console display. Character-at-a-time output, which is what happens in a PC when the console is being driven from the BIOS, means an API call is made per character written—with the attendant signature-fetching gyrations, producing a lot of software interrupts if significant display activity is required. That will definitely put a crimp on performance. The solution for such a case is for the operating system kernel to mitigate the overhead of processing a lot of software interrupts by allowing the calling function to specify how many bytes are to be output, which means that, conceivably, a full screen repaint could be done in a single API call. That's how it is done in UNIX and others.

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
 Post subject: Re: Multiple interrupts?
PostPosted: Sun Aug 23, 2015 11:59 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8511
Location: Southern California
I'm not familiar with x86 and BIOS methods, so I hope this isn't a waste of attention; but since you're using the NMOS 6502, before the 65c02 came along with its JMP(abs,X) instruction, a way to do an indirect jump using a jump table with the NMOS 6502 was:
Code:
                         ; Start with function (an even number) in X.
        LDA  TABLE+1,X   ; Read high address byte from the actual table, and
        PHA              ; push it.  Low byte comes next, below.
        LDA  TABLE,X     ; Be sure to make the table reflect start addresses
        PHA              ; minus 1, since RTS increments the address by 1.
        RTS              ; RTS does the absolute indexed indirect jump.

Then to keep the performance up for true interrupts, you can avoid BRK altogether with its high overhead and do this:
Code:
        LDX  #<function_number>
        JSR  <BIOS>
        <continue>

and "BIOS" is the label for the above starting with LDA TABLE+1,X. The routine you jump to will end with RTS, taking you back to where it says "<continue>". A particular function number can remain that number (which you'll probably give a meaningful name to), even if the addresses in the table have to change with later updates.

If you're using something like a Commodore 64 where you really can't use the CMOS version, you could still make a macro of the above routine, to get it on a single line, as BDD suggested with his example of "INT x" where "x" is the function number-- and actually I would give it a meaningful name. (You can read about the differences between the CMOS and NMOS 6502 in this article.)

In the above piece of code, the table has two consecutive bytes for each entry. This means you can't have a table of more than 128 entries, and depending on what you start with, you might have to put the entry number in the accumulator and do ASL before putting it in X. (That's why the first comment line says you must start with an even number in X.) A way around that is to split the table into two halves, one half having the high bytes and one having the low bytes. Now each half, indexed by the same number in X or Y compared to the other half, can be up to 256 bytes, meaning you can have 256 entries, even though they're two bytes each. It would go like this instead:
Code:
        LDA  high-byte table, X     ; Again, be sure to make the table reflect start addresses
        PHA                         ; minus 1, since RTS increments the address by 1.
        LDA  low-byte table, X
        PHA
        RTS

This technique is useful for token threading which has been used in interpreted BASIC and other interpreted languages. There's more discussion on it in this article in the 6502.org wiki.

_________________
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?


Top
 Profile  
Reply with quote  
 Post subject: Re: Multiple interrupts?
PostPosted: Mon Aug 24, 2015 7:58 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10938
Location: England
BigDumbDinosaur wrote:
Interrupt service routines should always be arranged so that branches are not taken unless absolutely necessary.

What you mean to say is that it might be worth considering the cost of taken branches - but only if you also consider every other possible saved cycle.

Here's how to look at it: How many cycles unavoidably in the preamble and postamble? How many cycles in the latency-sensitive paths through the interrupt handler? How many cycles saved? What's the proportion? Where else might cycles be saved? How might this minuscule increase in latency affect my application?


Top
 Profile  
Reply with quote  
 Post subject: Re: Multiple interrupts?
PostPosted: Mon Aug 24, 2015 11:05 am 
Offline
User avatar

Joined: Sat Aug 22, 2015 8:54 pm
Posts: 31
Thank all of you for your responses.
So what I need to do is have the handler check for BRK and branch if it is a BRK otherwise fall through if it was an IRQ, correct?

Quote:
A way around that is to split the table into two halves, one half having the high bytes and one having the low bytes. Now each half, indexed by the same number in X or Y compared to the other half, can be up to 256 bytes, meaning you can have 256 entries, even though they're two bytes each.


GARTHWILSON, could I make the table look something like:

High byte, addr 0
Low byte, addr 0
High byte addr 1
Etc...

Instead of two separate tables?

_________________
It may look hard, but it won't take long if you take it one byte at a time.


Top
 Profile  
Reply with quote  
 Post subject: Re: Multiple interrupts?
PostPosted: Mon Aug 24, 2015 7:49 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8511
Location: Southern California
nkeck72 wrote:
Thank all of you for your responses.
So what I need to do is have the handler check for BRK and branch if it is a BRK otherwise fall through if it was an IRQ, correct?

I would not use BRK for this myself at all, but my uses require really hot interrupt performance.

Quote:
Quote:
A way around that is to split the table into two halves, one half having the high bytes and one having the low bytes. Now each half, indexed by the same number in X or Y compared to the other half, can be up to 256 bytes, meaning you can have 256 entries, even though they're two bytes each.

GARTHWILSON, could I make the table look something like:

High byte, addr 0
Low byte, addr 0
High byte addr 1
Etc...

Instead of two separate tables?

Yes, that is the arrangement used by my first code example. Remember that low byte always goes at the lower address. The splitting was for being able to get more than 128 addresses in the table with normal ,X indexed addressing.

_________________
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?


Top
 Profile  
Reply with quote  
 Post subject: Re: Multiple interrupts?
PostPosted: Mon Aug 24, 2015 7:56 pm 
Offline
User avatar

Joined: Sat Aug 22, 2015 8:54 pm
Posts: 31
Makes sense. Thanks!

_________________
It may look hard, but it won't take long if you take it one byte at a time.


Top
 Profile  
Reply with quote  
 Post subject: Re: Multiple interrupts?
PostPosted: Tue Aug 25, 2015 5:52 am 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1948
Location: Sacramento, CA, USA
BigEd wrote:
BigDumbDinosaur wrote:
Interrupt service routines should always be arranged so that branches are not taken unless absolutely necessary.

What you mean to say is that it might be worth considering the cost of taken branches - but only if you also consider every other possible saved cycle.

Here's how to look at it: How many cycles unavoidably in the preamble and postamble? How many cycles in the latency-sensitive paths through the interrupt handler? How many cycles saved? What's the proportion? Where else might cycles be saved? How might this minuscule increase in latency affect my application?

I follow Ed's line of thinking here, but I concede BDD's point that hardware IRQs can be offered preferred treatment at no coding cost (in my example), so I edited it appropriately. Saving and restoring the contents of the Y register may also be avoided (saving 11 more cycles in my example) for the hardware service section, again at little or no coding cost, but only if the hardware ISR doesn't need the use of it. It's difficult for me to imagine an example where a difference of a dozen clock cycles per IRQ could have significance, but I may just be suffering from a temporarily-limited imagination.

Mike B.


Top
 Profile  
Reply with quote  
 Post subject: Re: Multiple interrupts?
PostPosted: Tue Aug 25, 2015 6:12 am 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8390
Location: Midwestern USA
barrym95838 wrote:
It's difficult for me to imagine an example where a difference of a dozen clock cycles per IRQ could have significance...

It all depends on what the ISR is servicing.

If it's a 100 Hz timer interrupt from a 65C22, a dozen clock cycles won't matter a lot to an MPU running at a reasonable speed. On the other hand, if it's a 65C51 running at 19,200 bps and handling CBAT, those IRQs may come at the rate of over 1900 per second for reception alone, assuming 8N1 data format. Suddenly those extra dozen clock cycles per IRQ serviced have scaled to 22,800 extra cycles for each second that the incoming data rate is sustained.

Now consider transmission. A full screen paint of a serial terminal display, assuming an 80 × 24 display matrix, requires 1920 bytes, not counting escape sequences. There's your 22,800 extra cycles again. You can get a whole lot of foreground processing done in 22,800 clock cycles, which is the main reason for keeping your ISR as succinct as possible.

Garth runs his workbench computer in situations where the interrupt rate can be tens of thousands per second. Needless to say, at that rate an extra clock cycle here and there in the ISR can really put a crimp in performance.

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
 Post subject: Re: Multiple interrupts?
PostPosted: Tue Aug 25, 2015 7:58 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10938
Location: England
BigDumbDinosaur wrote:
... IRQs may come at the rate of over 1900 per second for reception ... those extra dozen clock cycles per IRQ serviced have scaled to 22,800 extra cycles for each second

Dealing with high speed serial is a good example, but I'm not sure extra cycles per second is the best way to look at this. 1900 interrupts per second allows us 526 ticks of a 1MHz clock for each - as an absolute maximum which would allow nothing else to be done - so 11 cycles of overhead is 2% of our budget. If our clock is faster than 1MHz, so much the better. If our interrupt service routine uses say 50% of our budget, then that extra 2% has knocked 4% off the time available for other tasks. The tighter our original budget, the more dramatic an effect from that 2% overhead. 11 cycles is everything if you only have 11 cycles free. If you have 200 cycles free, not so much. Building a system with a faster clock might be the easiest way to get out of jail!

BTW those 11 cycles come from the example of saving or not saving an index register - the original point was about rejigging code to save 1 cycle from a branch not being taken. These are very different cases, by a factor of 11.

It is notable that serial processing takes quite an effort. That's why having a FIFO in the UART can be a big advantage, likewise arranging for the interrupt servicing to place characters into a buffer, rather than forcing the application to deal with each character in real time. The early BASIC from Ohio would save by LISTing and load by reading over serial. It was necessary to stuff line end characters with lots nulls, to give the interpreter time to digest each line before the first character of the next line comes through.

This also shows the benefit of having flow control in your serial interface, and of detecting overrun from your UART.

Even harder of course is the case of bit-banging a serial protocol, but at reasonable line speeds you'd avoid using interrupts for that - just too much overhead.


Top
 Profile  
Reply with quote  
 Post subject: Re: Multiple interrupts?
PostPosted: Tue Aug 25, 2015 8:06 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8511
Location: Southern California
Quote:
It's difficult for me to imagine an example where a difference of a dozen clock cycles per IRQ could have significance,
and
Quote:
Garth runs his workbench computer in situations where the interrupt rate can be tens of thousands per second. Needless to say, at that rate an extra clock cycle here and there in the ISR can really put a crimp in performance.

Yes, although it's rare that I go over about 24,000 per second, I have topped out at about five times that (around 120,000 per second, based on a VIA T1). Phase 2 is at 5MHz.

_________________
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?


Top
 Profile  
Reply with quote  
 Post subject: Re: Multiple interrupts?
PostPosted: Tue Aug 25, 2015 10:47 am 
Offline
User avatar

Joined: Sat Aug 22, 2015 8:54 pm
Posts: 31
I am running my system at 20MHz (I have a non-MOS tech.-chip) - and the only IRQ I expect right now is if the user wants to reset via software (e.g. CTRL-ALT-DEL). Otherwise I may not have used BRK for the reasons above. The time between IRQs is valuable - if you waste it bad things could happen, like corrupted serial data in the example above. Although, it was an idea - memorized jsr values (I have bad memory) I thought was kinda tedious - then I remembered x86 INT. I thought I could use the existing interrupt system - thus the idea of using BRK - and soft-vector it using a BRK handler. IRQs aren't a huge concern right now- the project I am working on is a BIOS for a multipurpose system anyone can write their own OS for. Also, if the user didn't want IRQs to be held up, they could avoid the system period - like (again) the x86 INT.

_________________
It may look hard, but it won't take long if you take it one byte at a time.


Top
 Profile  
Reply with quote  
 Post subject: Re: Multiple interrupts?
PostPosted: Tue Aug 25, 2015 11:08 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10938
Location: England
I hope you're hearing the message that most here wouldn't choose BRK, even though we're agreeing that it could be used. (The memorising JSR locations doesn't seem like a good reason to me to choose BRK - for one thing, you only need one or two routines to call if you use A to choose your service, and for another you need some documentation in any case to cover what OS services you provide. Some symbolic constants in an assembly header file are going to help readability and reduce what you need to remember.)

But I just thought of another disadvantage to using BRK: you've got a copy of P on the stack, which you don't really need or even want. Because it can be useful for the OS to return status in the flags - C certainly, and possibly in N and Z - you'll need an extra (early) PLP and a late PHP before your RTI, or you'll need some tweaking to your stacked PC so you can use RTS. Or you forgo returning status in the flags, of course.


Last edited by BigEd on Tue Aug 25, 2015 11:36 am, edited 1 time in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: Multiple interrupts?
PostPosted: Tue Aug 25, 2015 11:17 am 
Offline
User avatar

Joined: Sat Aug 22, 2015 8:54 pm
Posts: 31
Good point... and I am getting that most wouldn't choose BRK.

How many cycles does it take to execute a BRK vs. a JSR/RTS? Are they the same?

Instead of BRK then, maybe have one address to JSR to and have that address contain the vectoring code? That way they can IRQ every other clock cycle and the routine wouldn't bother it. And still have the jump table and stuff?

_________________
It may look hard, but it won't take long if you take it one byte at a time.


Top
 Profile  
Reply with quote  
 Post subject: Re: Multiple interrupts?
PostPosted: Tue Aug 25, 2015 11:35 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10938
Location: England
I think BRK will cost you one or two extra clock cycles, or rather more if there's a lot of IRQ/BRK preamble code.

Indeed, you can do all the same tricks using a JSR instead: a service in A and a jump table.

Cheers
Ed


Top
 Profile  
Reply with quote  
 Post subject: Re: Multiple interrupts?
PostPosted: Tue Aug 25, 2015 11:39 am 
Offline
User avatar

Joined: Sat Aug 22, 2015 8:54 pm
Posts: 31
Thanks a lot guys! This helps a lot. Will keep you posted on the BIOS!

_________________
It may look hard, but it won't take long if you take it one byte at a time.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 81 posts ]  Go to page Previous  1, 2, 3, 4, 5, 6  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 27 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: