6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sun Nov 24, 2024 12:20 am

All times are UTC




Post new topic Reply to topic  [ 40 posts ]  Go to page 1, 2, 3  Next
Author Message
 Post subject: BRK detection
PostPosted: Wed Nov 27, 2002 7:12 pm 
Offline

Joined: Wed Sep 04, 2002 4:08 pm
Posts: 57
Location: Iowa
Hello!

I thought checking the B flag in the status register would indicate a BRK-caused interrupt, but to my surprise it seems to always be set. A close examination of the 6502 docs indicates that not only BRK but RTI and PLP set the B flag. Is there no way to clear B except perhaps for a processor reset? Anyone know why this is?

What is the proper way in an ISR to detect a BRK instruction?

Scott


Top
 Profile  
Reply with quote  
 Post subject: BRK Handler
PostPosted: Wed Nov 27, 2002 9:26 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 9:02 pm
Posts: 1748
Location: Sacramento, CA
Hi Scott,

AS I understand it, the BRK Flag gets set when the BRK opcode is executed. The processor pushes the return address and Status Reg to the stack then does an indirect jump thru the IRQ vector @ $FFFE,$FFFF.

Once the jump occurs, the BRK flag gets reset. The only way to detect a BRK is to read the Status Reg from the stack.

My SBC's and my Simulator both have a BRK detect routine at the beginning of the IRQ service routine. I'll enclose it here as just one example of how th detect a BRK.

Code:
Interrupt      PHX                     ;
               PHA                     ;
               TSX                     ; get stack pointer
               LDA   $0103,X           ; load INT-P Reg off stack
               AND   #$10              ; mask BRK
               BNE   BrkCmd            ; BRK CMD
               PLA                     ;
               PLX                     ;
               jmp   (INTvector)       ; let user routine have it
BrkCmd         pla                     ;
               plx                     ;
               jmp   (BRKvector)       ; patch in user BRK routine



Hope this helps!

Daryl
http://65c02.tripod.com/


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Wed Nov 27, 2002 11:00 pm 
Offline

Joined: Wed Sep 04, 2002 4:08 pm
Posts: 57
Location: Iowa
Thanks for the help! I still have questions about BRK, though. I also have a simulator (unknown source) and an SBC, and my code was as follows:

Code:
CheckBrk
; todo... this is broken; it always goes to BrkHandler.
    php                     ; Get the processor status into A
    pla
    and #BFlag              ; Check the B flag
    beq IrqDone
    jmp BrkHandler


On my simulator, it behaved as I expected, where B was set through the BRK instruction, and at the end of the ISR, the RTI cleared it (by pulling the old flags from the stack and overwriting the set B flag). I verified this simulator behavior by both examining its source code, and through actually running it.

On the SBC, however, I found that I was entering BrkHandler all the time. In fact, it didn't even take a BRK instruction; a simple IRQ (from my serial chip) would do it. I found in the 6502 documentation that B is set by three instructions, BRK, RTI, and PLP, and therefore seems to have no way of being unset, as these three instructions seem to me to be the only ways to actually unset B. I'm baffled; this makes no sense!

I suppose I could detect a BRK by examining the opcode as referenced by the return PC on the stack (probably about seven lines of code), but it seems to me that the B flag itself is useless.

Any thoughts? Should I just ignore the B flag and BRK in general (I was hoping to use it as a soft interrupt eventually)?

Scott


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu Nov 28, 2002 10:34 am 
Online
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8546
Location: Southern California
The BRK was mainly for debugging and patching code in the days when re-assembling and programming a new ROM took longer (and was very expensive if the ROM wasn't erasable!) Converting your tested patches into normal code could also take some work, and even introduce new bugs if you weren't careful. The instruction seems to have outlived its usefulness.

I've never had any use for the BRK, so I really had to study the books on this one. Unfortunately, none of my books were clear on this, and one seemed to contradict something in the others. The only thing left to do was to actually try it on the workbench computer. (Why didn't I do that in the first place?)

As you know, you can't test the B bit directly, so the processor status must be pulled off the stack into the accumulator to test a bit. Testing this way, the only way I ever found the B bit clear was in the processor status register copy that was pushed onto the stack by a hardware IRQ, before the RTI, using PLA PHA in the ISR. When I used PHP PLA, I found, just as you did, that the B flag appeared to be set all the time.

Garth


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sat Jan 04, 2003 10:12 pm 
Offline

Joined: Sat Jan 04, 2003 10:03 pm
Posts: 1706
The BRK instruction was introduced as an aide towards debugging (BReaKpoint). A hardware bug originally caused it to push the PC+2 address on the return stack. As a result, later versions of the 6502 documentation suggests using BRK as a means of invoking operating system functionality, where the byte following the BRK opcode is used as a function number. For example, some hypothetical system could be implemented like this:

LDA #device_id
LDX #address_of_text
LDY #length_of_text
BRK #SYS_OUT

On the 6502, the BRK instruction has very little utility outside of debuggers, but with the 65816, it has much more utility. It makes invoking operating system services easier, since the CPU does more of the work in maintaining the bank registers for you. The opcode is also two bytes shorter, providing reduced memory footprint.

Since the BRK instruction is treated as a software interrupt, and therefore preserves the P register on the stack, it is easier to make a multitasking operating system using BRK than using other techniques. While executing inside the kernel, a task switch performed at an inappropriate time can create serious problems, such as deadlock, or worse, an all out crash and burn. By coding the kernel so that it can only switch tasks upon returning from an interrupt, the kernel is made more robust, smaller, and more efficient.

Most people don't know what to do with the BRK instruction because they don't understand operating system design. For something like the 6502, which doesn't have the memory capacity for general purpose multitasking, that's understandable. But the 65816 opens up whole new vistas for computing with the 65xxx platform, which includes multitasking and other sophisticated operating system techniques. With an external MMU (simple enough to make, though it does add to the propegation delays with memory), it even supports memory protection and linear/physical memory remapping often found on other "big-wig" processors.


Top
 Profile  
Reply with quote  
PostPosted: Sun Jan 05, 2003 6:40 am 
Offline

Joined: Wed Sep 04, 2002 4:08 pm
Posts: 57
Location: Iowa
After pursuing the BRK issue more, I concluded that it was futile. My findings show that BRK is absolutely, completely useless except in the one special case where the ONLY cause for interrupt can be from it (i.e., no interrupt driven I/O). I'll explain shortly.

First off, I was interested in BRK specifically because I thought I could use it as an OS call (to my own written OS). This would be similar to DOS INT 21h calls, etc. I'm sure I'm not alone on this forum in my experience professionally with real time multitasking/multithreaded/multiprocess operating systems; I know that interrupts are obviously a necessity to the success of context switches and I/O calls, etc., and I've seen it first hand while tracing through the source code to at least one real time operating system, not to mention using INT on the x86.

Anyway, now for my findings... Like I said, the 6502 sets the B flag not only on execution of BRK, but also on PLP and RTI. Since those two instructions provide the only hope of providing a way to manipulate the B flag (by pulling a data value with the B bit set back into the status register), it seems impossible to clear the B flag. I've confirmed this fact not only on an actual 6502 and even a 65C02 chip, but in reference documentation, too! (Take a look yourself at any 6502 documents... RTI and PLP pull flags off the stack, but set B instead of using the bit from the byte pulled!). It surprises me that the designers of the 6502 chose to do this, but so they did. It's hard to dismiss as a bug, too. Any thought into how logic circuits work would lead to the conclusion that setting only the B flag while pulling the other flags on RTI and PLA was a deliberate design decision, not a bug.

I explored a trick way of detecting a BRK. Suppose in your ISR you examine the byte pointed to by the saved program counter. You should be able to tell what the opcode was that was interrupted; if it was the opcode for BRK, great! Otherwise, it was another opcode that was interrupted, and therefore not a BRK condition. Ah, but then we have the caveat of that PC+2 saved on BRK, while PC is saved unmodified on a hard interrupt. No problem, check for the opcode two bytes back from a saved PC, right? If it's a BRK opcode, it MUST have been a BRK. Oops, what if the byte at PC-2 is an operand of a three byte instruction preceding the one interrupted, and that operand happens to be the same value as the BRK opcode? For example, what if the instruction interrupted was preceded by LDA $0400? The $00 byte of that instruction looks like the opcode for BRK.

Checkmate.

Everything I've read about BRK indicates that it was used to patch PROM code, because you can always set PROM bits to zero (but you may not be able to set them back to ones) by blowing the little fuses or permanently charging the floating gates, etc. So saving PC+2 makes sense, since after the patch you do not wish to re-execute the BRK, although in a hardware interrupt, you DO want to execute the interrupted instruction which didn't get executed yet. This doesn't seem like a bug to me, and certainly if it was, it would have been fixed in the 65C02. You'd just have to make sure to patch two one-byte instructions or a single two-byte instruction.

Interestingly, the Commodore 64 Programmers Reference Guide has a little introduction to 6502 assembly, and the example programs end with BRK. I tried this in my youth using Supermon, and surprise surprise--they didn't work. When I ended programs RTS, however, they worked.

There is only one situation where a reliable BRK can be detected, and that's if NO other sources of interrupt are possible. Thus if you find yourself in the ISR, it MUST have been from the BRK, since the interrupt couldn't have been from any other source. Of course, that excludes any interrupt driven I/O or timers--not likely.

You could possibly say that if no hardware claims an interrupt, then it must have been from a BRK (for example, you're in the ISR and no timers have expired, nor have any characters been received on your serial port, nor is the transmitter enabled). However, since the 6502 interrupt line is usually passively pulled high by a resistor and thus could be slow to rise, it is possible that an extra, unjustified interrupt could be generated after the ISR is executed, thus fooling it into thinking a BRK occurred when that wasn't the case.

I haven't looked at 65816 documentation, but I assume that at least in "6502 emulation" mode things aren't much different. I'd be pleasently surprised if this worked better in 16-bit mode.

I'd love to be proved wrong on this or shown a way to do it, but my suggestion to anyone wishing to benefit from my experience is to stay the heck away from BRK!!!


Top
 Profile  
Reply with quote  
PostPosted: Sun Jan 05, 2003 8:06 am 
Offline

Joined: Sat Jan 04, 2003 10:03 pm
Posts: 1706
schidester wrote:
After pursuing the BRK issue more, I concluded that it was futile. My findings show that BRK is absolutely, completely useless except in the one special case where the ONLY cause for interrupt can be from it (i.e., no interrupt driven I/O). I'll explain shortly.


Your explanation isn't congruent with observed uses for the BRK instruction. I *know* that BRK was used for debugger breakpoint support (years ago, I coded this for a Commodore 64. I don't think the 6510 differs enough from the 6502 to the point that the B flag behavior is different). If the B flag is so "useless," then it should be true that the BRK condition is 100% undetectable relative to a normal IRQ. Clearly, this isn't the case. Commodore's kernel distinguishes between BRK and IRQs just fine.

Quote:
Like I said, the 6502 sets the B flag not only on execution of BRK, but also on PLP and RTI. Since those two instructions provide the only hope of providing a way to manipulate the B flag (by pulling a data value with the B bit set back into the status register), it seems impossible to clear the B flag.


Why would you care if the B flag is set after your ISR has returned? What you're concerned with is the value of the B flag pushed onto the stack, not what's currently in the P register.

Quote:
Interestingly, the Commodore 64 Programmers Reference Guide has a little introduction to 6502 assembly, and the example programs end with BRK. I tried this in my youth using Supermon, and surprise surprise--they didn't work. When I ended programs RTS, however, they worked.


That being said, I wrote a large number of BRK handlers, and even GEOS/64 has custom BRK handlers, and they seem to work just fine.

I also would like to point out that executing a BRK on a bone-stock V3 C64 kernel will behave as if an NMI is received: that is, exactly as if you hit RUN-STOP and RESTORE. I'm not sure how it behaved on other kernel versions.

Quote:
There is only one situation where a reliable BRK can be detected, and that's if NO other sources of interrupt are possible.


Simply not true.

Quote:
I haven't looked at 65816 documentation, but I assume that at least in "6502 emulation" mode things aren't much different. I'd be pleasently surprised if this worked better in 16-bit mode.


The BRK instruction has its own interrupt vector in native mode; thus, the B flag is no longer used nor supported (and, in fact, is re-allocated to a different purpose all-together).


Top
 Profile  
Reply with quote  
 Post subject: Headaches... :(
PostPosted: Sun Jan 05, 2003 7:06 pm 
Offline

Joined: Sat Jan 04, 2003 10:03 pm
Posts: 1706
In re-reading my message above, it looks like a bit on the 'testy' side for my liking. I must apologize in advance.

I'm currently suffering from coughs and severe headaches that won't let me sleep and which is responsible for severe stiff necks and whiplash-like symptoms. So in a sense, I guess I am quite testy right now. :( But it's not my intention to be so, and please don't think I'm taking my frustrations out on you -- I really didn't mean to.

Please bear with me as I have another doctor's appointment this coming 7 Jan. Unfortunately, like the last time, I'm pretty sure they'll sit there and gape at me, "I don't know what it is. You'll just have to sit this one out..." :x

Bahh, I'm rambling now. I'm going back to bed. :(


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sun Jan 05, 2003 9:34 pm 
Online
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8546
Location: Southern California
Again, you can test the B flag in an ISR (even before polling for other causes of interrupt) by doing:

PLA
PHA
AND #00010000B

The following will not work:

PHP
PLA
AND #00010000B

IOW, you can only test the record of P that was put on the stack by the interrupt itself. If you try to put it on the stack yourself with PHP, even at the beginning of an ISR, it won't work.


Now, on to the usefulness of BRK:

If you have found a legitimate use for BRK in operating systems, I would like to hear about it. I'm not necessarily challenging you, but asking for education.

In all my work and hobby 6502 experience, I have never had any use for BRK. Since the instruction goes into the actual code instead of appearing unexpectedly at random times like an IRQ, you may just as well use JSR, and then you'll have the equivalent of all the BRK vectors you could possibly want. It's not like the 6502 had a hardware divide or tangent instruction where you might want an overflow exception to transfer control to another routine so you don't have to lengthen the main code to test for inputs that would cause those situations before the fact. Using the JSR (or possibly JSL on the 65816), you wouldn't need the following signature byte, and the subroutine can save P anyway if you want.

So again the only use I see for BRK is the patching while developing code with the limitations that no longer exist. With a fast PC, re-assembly just takes a second. You might as well correct the code the right way instead of put a band-aid on it. With my setup on the workbench computer, I don't normally have to keep programming EPROMs during development; but if I did, my programmer can do an 8Kx8 EPROM almost as fast as I can get it in and out of the socket. IIRC, it's between 2000 and 4000 bytes per second, unlike what we had 15 years ago. The little extra time to re-assemble and just do another erasable EPROM is saved by not having to later work the code over yet again to integrate patches that were done and tested with the BRK instruction.

When I started working with this stuff in 1982 on an AIM-65 in school, we always ended our hand-assembled routines with BRK to transfer control back to the monitor program. Now with plenty of experience behind me, I think I would do it differently if I had to write the monitor program myself.

On another note, I've never done true multitasking. I haven't needed to because I've always been able to do the 2 or 3 needed things at once with real-time deadlines by using interrupts for pseudo-multitasking. I have an article on how to do true multitasking in Forth on 6502 and other small computers. It's pretty simple and has very little overhead. The stack space on the 6502 would not be suitable for doing 20 tasks at once, but certainly 3 would work fine, and maybe 4 or 5. It does not use the BRK instruction either.

This brings me back to my original question for those who have experience with multitasking operating systems-- What real use does BRK have today, if any?

Garth


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sun Jan 05, 2003 11:45 pm 
Offline

Joined: Fri Aug 30, 2002 2:05 pm
Posts: 347
Location: UK
Quote:
In all my work and hobby 6502 experience, I have never had any use for BRK.


I have, to call an ISR. When I built my plotter the timers were only
used to wait for the motors/solenoid to finish moving so interrupts
were only on during drawing. If the ISR found the draw buffer empty
it didn't initialise the timers for the next interrupt.

To get it all started the routine that wrote to the buffer checked a flag
at the exit like this ..

Code:
 LDA   drawflag
 BNE   exit

 BRK
 .byte $00
exit
 RTS


.. and so got the whole thing going again.

Not needed to use it elsewhere though.

Lee.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon Jan 06, 2003 12:37 am 
Offline

Joined: Wed Sep 04, 2002 4:08 pm
Posts: 57
Location: Iowa
After reading your post, Garth, I FINALLY realized where my misunderstanding lay. Now I know that what is in the status register cannot be used to detect the BRK condition--it must be the status register that is saved on the stack! I suppose I didn't see the vital importance of this in the post from Daryl until I examined it again just now. Sometimes it takes twice to get it through a thick skull.

In defense of myself I must say that normally one does check the flags from an actual status register to determine the source of an interrupt (for example, the status register of a UART); why should the 6502's status register be any different? I suppose the designers of the 6502 found a way to optimize their circuit this way. If anyone has any light to shed on this, I'd be interested in learning.

kc5tja, no offense is taken; I find the discussion rather thrilling actually. Get well soon, by the way. If I had known the proper technique for detecting BRK (and it's my fault for not catching it sooner), I wouldn't have written such a long-winded post protesting its existence, it's just that I examined every other conceivable technique and came up with nothing. Not only is reading the status from the stack the proper way to do it, but it appears to be the ONLY way to do it.

This is a moot point now, but the reason I was concerned with the status register AFTER an ISR is that the NEXT time through an ISR, that darn B flag appears to remain set from the previous ISR's RTI. I thought if I at least cleared B in my ISR by hand (using either RTI or PLP, which provide the only hope of clearing the B flag by software) then the next time through the ISR I could detect the BRK condition using B. Again, though, apparently that won't work anyway.

I checked the code in the Commodore 64 kernal's ISR and it uses the correct technique as demonstrated by Garth and Daryl. Interesting that BRK never worked for me on those old Commodore 64 programming examples, but perhaps it was a problem with the monitor, not the kernal.

On a side topic, at least what I said about detecting a BRK by examining PC-2 remains true for NMI; I think I saw someone's code fragment somewhere that detected a skipped BRK on NMI by examining the opcode at PC-2 in the NMI handler; this is risky. On a 6502, this is an insurmountable bug; the 65C02 doesn't have this problem, I hear.

Garth, I believe the main reason for using software interrupts for multitaksing OS calls has to do with disabling interrupts during execution of OS functions. When a task calls the OS to perform a function, such as a character read from a UART, the OS should be in the position, uninterrupted, to switch that task out of context (block), and place a different task into context. When the blocked task's character is available, the OS's ISR (also in an interrupt-disabled state) can switch it back into context to process the character it was waiting on. This task switching needs to occur without interrupts enabled. Tack on a memory manager (probably rare in a 6502 system) and disabling interrupts becomes almost obligatory. I believe in the 68000 series of processors, this is called "supervisor" mode. On the 6502, you can use JSR to make OS calls in a multitasking environment, but in each OS subroutine, you'll probably want to disable interrupts. Not to mention you have to implement a jump table because subroutine addresses are bound to move around from version to version of your OS. Or you can use BRK, with a function number loaded into the accumulator, for example, and the ISR can sort out the call addresses, not to mention interrupts are already disabled.

Now that I think about it, another compelling reason is that using a software interrupt for OS calls means the OS functions don't have to be made reentrant. Reentrant OS functions can be a pain in multitasking. Using interrupts before entering OS functions ensures that an OS call can never be entered twice before exiting (just like an ISR itself, which should never be reentered).

I hope that's an adequate explanation. My experience with multitasking has to do with a 68K processor; I have no multitasking experience with the 6502, so take this with a grain of salt.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon Jan 06, 2003 12:57 am 
Offline

Joined: Wed Sep 04, 2002 4:08 pm
Posts: 57
Location: Iowa
Quote:
I also would like to point out that executing a BRK on a bone-stock V3 C64 kernel will behave as if an NMI is received: that is, exactly as if you hit RUN-STOP and RESTORE. I'm not sure how it behaved on other kernel versions.


Sorry for extra discussion, but I found this interesting after reading your post, kc5tja. Here is the Commodore 64 ISR (I found this on the web and can only assume it is accurate; everything on the web is, right?)

Code:
; IRQ entry point

FF48   48         PHA
FF49   8A         TXA
FF4A   48         PHA
FF4B   98         TYA
FF4C   48         PHA
FF4D   BA         TSX
FF4E   BD 04 01   LDA $0104,X
FF51   29 10      AND #$10
FF53   F0 03      BEQ $FF58
FF55   6C 16 03   JMP ($0316)   ; normally FE66

FF58   6C 14 03   JMP ($0314)   ; normally EA31


It appears that any monitor program must be responsible for setting the vector located at $0316 to intercept BRK. The monitor I used probably never did that, and as I recall, indeed the examples I tried ended with that READY prompt as if RUN/STOP-RESTORE had been pressed.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon Jan 06, 2003 2:03 am 
Offline

Joined: Sat Jan 04, 2003 10:03 pm
Posts: 1706
GARTHWILSON wrote:
This brings me back to my original question for those who have experience with multitasking operating systems-- What real use does BRK have today, if any?


1. It saves you from having to interject, even via a JMP to a common exit point, common code to optionally perform a task switch, and,
2. It provides more freedom in choosing the kernel layout (e.g., no jump tables to maintain, no fixed addresses for entry-points, etc).
3. It provides the only reliable method of crossing an address space boundary legitimately in a memory protected environment. JSRing to the kernel directly can cause a program to fault (attempting to execute privileged code via an unprivileged task), while BRK provides a controlled entry point to the privileged code. Thus the MMU can detect the BRK instruction on the bus, and automatically shift into privileged mode with a high degree of confidence that nothing bad will happen.

Having a task switch occur while executing a kernel call is exceedingly dangerous, so it's always a good idea to defer such an action until *after* you're done servicing an interrupt. BRK just happens to be an interrupt, so what better place to put the task switch code at the end of the BRK/IRQ handler?

Like I said, for most 6502 and low-end hobby installations, BRK's only benefit is in debugging. But 65816 systems with full-bore multitasking systems, especially those with MMUs, BRK is the only reliable way to invoke OS services.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon Jan 06, 2003 7:41 am 
Online
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8546
Location: Southern California
From Lee's post:

> > In all my work and hobby 6502 experience, I have never had any use for BRK.
>
> I have, to call an ISR. When I built my plotter the timers were only...

Were the plotter timers the only thing for the ISR to respond to? One simple way to do it if there were other possible interrupt sources and you want to use the same routines in non-interrupt mode, would be to have a simple ISR poll to find out which source was responsible for the interrupt and then go to the appropriate subroutine to service it. Then if you want to do it without the interrupt, you use JSR and skip the polling. This might be more structured and modular. (This is just a comment and an idea. I'm not presuming to know it's necessarily better for your particular application.)


From schidester's post:

> After reading your post, Garth, I FINALLY realized where my misunderstanding lay...
>
> In defense of myself I must say that normally one does check the flags from an
> actual status register to determine the source of an interrupt (for example, the status
> register of a UART); why should the 6502's status register be any different?
> I suppose the designers of the 6502 found a way to optimize their circuit this way. If
> anyone has any light to shed on this, I'd be interested in learning.

BRK does not respect the interrupt-disable flag. You wouldn't want it to, or patching code with it would be harder in ISRs or anywhere I is set. OTOH, if the I bit was clear and a patch were getting executed, you might still want interrupts enabled (depending on the ungency of servicing them). So I suppose it makes sense that you'd have to check what was stacked at the last level to determine whether the interrupt was caused by hardware or a BRK.

> On a side topic, at least what I said about detecting a BRK by examining PC-2 remains
> true for NMI; I think I saw someone's code fragment somewhere that detected a
> skipped BRK on NMI by examining the opcode at PC-2 in the NMI handler; this is
> risky.

If I'm understanding you right, this sounds like really bad programming! I have visions of getting into a lot of trouble in a big hurry. If it ever does get sorted out and working, maintenance would be the next headache.

> Garth, I believe the main reason for using software interrupts for multitaksing OS
> [rest of paragraph considered, but omitted here for brevity]

Reading this stirs a few responses. One is that it's starting to make sense why one complaint I've read a few times about why the PC and Windoze are very unsuitable for real-time applications because the interrupt latency is so nondeterminate. It also makes me think non-preemptive multitasking can help avoid a lot of problems. The article I mentioned about simple, low-overhead multitasking on small systems in Forth delt with round-robin, non-preemptive multitasking. Each program to be run must be written with the multitasking in mind, and there are only certain places where it offers the system the option of switching to another task; but then task-switching only happens at points where it's a smaller job with fewer hazards. Of course as you mention, the I flag can be set or cleared at any time by software too, not just by interrupts and RTI.

> Using interrupts before entering OS functions ensures that an OS call can never be
> entered twice before exiting

But BRK can be entered endlessly without exiting, until the stack is overrun.

> (just like an ISR itself, which should never be reentered).

I can think of plenty of situations where you would want to re-enable interrupts during an ISR, like when a rare interrupt that takes a long time to service is interrupted by a more frequent interrupt that is more urgent but you can service very quickly. However if the same source is interrupting its own ISR, then you probably don't have enough processing power to keep up (or maybe something needs to be streamlined to make better use of the available power).

> I hope that's an adequate explanation. My experience with multitasking has to do
> with a 68K processor; I have no multitasking experience with the 6502, so take this
> with a grain of salt.

Although the 68K has interested me, I never actually got into it. I see that its interrupt latency however is not nearly as quick as the 6502's.

I hope none of this is taken to be combative and argumentative. I might sound that way sometimes when I want to better communicate what I'm thinking so the other person will deliver what I need to hear. I am interested in the multitasking, although it seems that my need for it is slowly diminishing. My home-brew Forth system has an easy way to install, prioritize, and delete ISRs on the fly, both in assembly and in high-level Forth, with very low run-time overhead. It does not use a rigid polling program that has to be changed every time there's a small change in possible interrupt sources or priorities. Still, this will never totally replace true multitasking, so I'll be glad to learn from what is presented on the forum.


Responding to kc5tja's post:

I guess I can see where you're coming from now. It's kind of a foreign idea to me because I have never had to work with someone else's OS on the 6502 since 1982 when we used the AIM-65's in school. I've always had full control of every speck of code, and my workbench computer quickly compiles applications on the fly every time I load them up to use them, so even the possibility of changing addresses in the kernel are no threat. I commented above about the problem of task-switching happening at the worst possible times.

Garth


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon Jan 06, 2003 3:48 pm 
Offline

Joined: Wed Sep 04, 2002 4:08 pm
Posts: 57
Location: Iowa
Garth,

Quote:
> In defense of myself I must say that normally one does check the flags from an
> actual status register to determine the source of an interrupt...

BRK does not respect the interrupt-disable flag.


All I meant was that I expected (wrongly) to examine the B flag (not the I flag) to determine whether BRK was the cause of interrupt.

Quote:
If I'm understanding you right, this sounds like really bad programming!


That was precisely my point! Somewhere (I forgot where) I saw NMI handler code that attempted to get around the "skipped BRK on NMI" bug in the 6502 by examining the opcode at the saved PC minus 2. I was hoping that someone reading this might not make that mistake if they didn't think about it.


Quote:
..PC and Windoze are very unsuitable for real-time applications because the interrupt latency is so nondeterminate...


Agreed. I think the main problem is the lengthy swap times to harddisk. Windows is always messing around with the harddisk, making any application execution indeterminant. Nonetheless, I read somewhere that DOS is the most popular embedded operating system by volume. Scary.

Quote:
there are only certain places where it offers the system the option of switching to another task


An operating system can of course include a number of features which either complicate it or simplify it. It depends on your needs. If you write your own OS, naturally you have the most flexibility.

Quote:
But BRK can be entered endlessly without exiting


I forgot about that. I was thinking that a timer event might signal a task switch in the middle of an OS call, thus possibly reentering the same OS call. However, BRK doesn't just happen anywhere, so already we have control of it causing reentrancy problems. Also, if you're not using preemption, it's not an issue anyway.

Quote:
I can think of plenty of situations where you would want to re-enable
interrupts during an ISR


Me too. On my little SBC project I have a "panic" button attached to NMI, whose handler basically drops into a monitor prompt, enabling interrupts to do I/O. Until the monitor returns to the interrupted program, the NMI-triggered monitor prompt can be thought of as one long ISR. Thanks for the correction. I was trying to illustrate that in a multitasking OS, you probably likewise want to disable (hardware) interrupts because they cause a context switch, when your OS may already be in the middle of switching tasks.

Quote:
I hope none of this is taken to be combative and argumentative.


Nope. Again an interesting discussion.


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

All times are UTC


Who is online

Users browsing this forum: No registered users and 12 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: