This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Keil 8051 interrupt ISR

I'm having problems with 8051 based ISRs. The problem occures when:

1- Interrupt A is being serviced.
2- Interrupt B occures and is serviced (in the middle of ISR A execution.
3- Sometimes ISR A fails to complete.

I'm using the C ISRs used in C51 without any register set defined ("using xx"). My understanding is that the ISRs should get entered and serviced mutually exclusive from one another without corrupting one another's stack. Is this not the case?

  • Interrupts DO work. My guess is you have an atomicity problem.

    Erik

  • "Interrupts DO work."

    What a particularly strange statement.

    An interrupt definitely does NOT necessarily work AS REQUIRED if the coder has done something incorrect.

  • I'm not a C51 guy but I hope I can help a little. It sounds as if Erik is correct: maybe your stack overflows, corrupting the return address of A? maybe you can use some kind of static variable to count the number of not yet finished ISRs to determine the depth of the stack?

  • 2- Interrupt B occures and is serviced (in the middle of ISR A execution.
    This seems to be a problem, no ISR should interrupt another ISR, are you doing something such as enabling interrupts or something inside an ISR? Why do you need to interrupt your interrupt? What are you doing inside the interrupt that you would even desire to interrupt it?

    Stephen

  • "Interrupts DO work."

    What a particularly strange statement.

    blabbering the above which is, by no means 'strange' or 'incorrect' would be something like "in the particular case you describe, the interrupts are generated correctly by the compiler/linker and thus the reason for your problem would have to be in your code."

    So, instead of typing a ton of blabber, I state the fact "interrupts DO work." and say "show your code"

    If whoever is hiding behind "John Malund" can not handle "short and concise" and want everything to be blabber, then I suggest she writes the blabber herself instead of having a cow about "short and concise".

    Erik

  • This seems to be a problem, no ISR should interrupt another ISR
    why not? the sole purpose of the IP register is exactly to make that possible.

    are you doing something such as enabling interrupts or something inside an ISR
    none of that would make another interrupt interrupt the ISR, only IP can do that.

    Erik

  • I've no problem with short and concise.

    However, additions of meaningless and superfluous baggage like your "Interrupts DO work." cannot be considered conducive to short or concise.

    You might as well say, "keyboards DO works", and "kettles DO works" and "wheels DO turn"; they'd be just as valid!

    Blabber is as blabber does.

  • Thanks to everyone for all the feedback so far.

    But I do need to be able to nest the interrupts (interrupt my ISR). I looked all over Keil C51 documentation and on the website and can't find a clear statement noting whether the C ISRs are nested or not. Does anyone know if they are nested?

    Also, the ISR is getting serviced correctly when Eveant A and B are occuring individually. The problem occures only when B happens in the middle of event A. Even at that, it doesn't always fail. It fails after 2 to 3 such interleaving events.

    I will do some debugging and provide feedback to the forum. Thanks,

  • "But I do need to be able to nest the interrupts [...]"

    Now you are running away too far and too fast...

    Do not state this as a fact! Instead state clearly _why_ you think that you need nested interrupts. An ISR should normally be very short, so the time for it to end should be short. So the processor should normally be able to schedule the next interrupt very quickly even if an ISR was currently active.

    Exactly why do you need to do so much in an ISR that you can't survive the latency of a previous ISR ending before the next ISR is serviced?

  • The reason for nesting the ISR is that interrupt A is a command to do something through an interface. The interface is running at slower frequency so it could take a short amount of time.

    Event B is very short and quick and happens quite often. So it's very likely to happen in the middle of A.

    I understand that I can que the event A command and service the command outside of ISR but that may cause another command (event A) to come in on top of the 1st one. So that's why I want to do command A in the ISR.

    Theoretically there should be no problems with this scenario. When I remove event B from being IRQ driven to polling, this problem goes away. But I rather have it IRQ driven.

  • But if IRQ A can happen at a higher frequency than you can process, then it really doesn't help to use nested interrupts.

    If you get more A requests than can be handled, some will be lost. By "locking" A from happen until you have serviced the previous one, you will quickly loose A events.

    If you queue the A events, then you can have up to "queue size" pending A events without loosing any of them.

    You really must put down on paper in what situations you may loose A events, and/or if there should be some form of handshake to pace the A requests until the previous request has been processed. This has nothing with the implementation of your software to do, but is part of the requirements specification.

    And the specification really must specify a limit to the A events that can happen, or under what circumstances A events are allowed to be lost - without such a specification, you can't design neither hardware nor software.

  • I do have a handshaking built in to my ISR so that's why I want to use nesting.

    A event is a USB SETUP command. Untill A event is serviced, the USB SETUP status will not go back to USB host. Thus, USB host knows when A event has ended by simply waiting for the handshake which will happen at the end of A ISR. This will ensure that another A event doesn't come down the pipe while busy.

    B event is another USB event that can happen in the middle of A event to a different EP. B event is a USB INTERRUPT EP.

    If I remove A servicing from ISR, then I can't use the USB handshaking mechanism as flow control.

  • The code is as follows:

    ===========Event A ISR==============
    void ISR_Sudav(void) interrupt 0
    { // EA = 0; // Try dsiabling all IRQs. Doesn't help
    // EZUSB_IRQ_DISABLE(); // Try disabling all USB IRQs. doesn't help. SetupCommand(); // Service command

    EZUSB_IRQ_CLEAR(); // Clear USB IRQ

    INT2CLR = bmSUDAV; // Clear SUDAV IRQ

    // EA = 1;

    // EZUSB_IRQ_ENABLE();
    } ==============Event B ISR =================
    { void ISR_EP1(void) interrupt 0
    { #ifdef USE_EP1_IRQ

    // EZUSB_IRQ_DISABLE(); // Try disabling IRQs. Doesn't help!

    // Do some stuff here

    P_EPIRQ = 0x04; // Clear USB IRQ

    // Clear USB IRQ EZUSB_IRQ_CLEAR(); // Clear USB IRQ

    // EZUSB_IRQ_ENABLE();

    }

  • interrupt A is a command to do something through an interface.

    What's that supposed to mean? An interrupt can't "be" a command. What really happens is that it signals a command having arrived from the outside, which you should queue away and get on with whatever you were doing.

    The interface is running at slower frequency so it could take a short amount of time.

    Then you need a better interface that doesn't take so long after having signaled a new command until you actually know what the command is.

    I understand that I can que the event A command and service the command outside of ISR but that may cause another command (event A) to come in on top of the 1st one.

    Well, that's why you queue the events, instead of just storing them, isn't it?