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?

Parents
  • 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.

Reply
  • 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.

Children
  • 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?

  • instead of the fiddeling (which by the way will never work), just use the IP

    Erik

  • The code posted appears to show two interrupt handlers attempting to service the same interrupt. Maybe it's some feature I'm not aware of, or maybe that isn't a copy and paste of the real code.

    In addition to this, there's a brace imbalance and a possible attempt to call the same function from two interrupts of possibly different priority levels.

    Might I suggest you reduce your code to the minimum that still shows the problem, then in the unlikely event you haven't found your mistake while doing so post the code using the tags intended for that purpose. Use copy and paste.

  • Erik, IP doesn't help me since both interrupt A and B have the same priority that I cannot change.

  • Is that you actual code? both interrupts are 0 this should be a compiler error. It should also be the an 8051 interrupt not the USB is this correct what is the vector address?
    An interrupt of the same or lower priority can not interrupt an in-process interrupt.
    Are you sure this is happening? or is the longer interrupt hold off the important one?

    What is the Chip Number and what are the two interrupts?

  • Hi Neil, The chip is EZUSB from Cypress semiconductor. The 8051 in there has some enhancements with a external vectored interrupt controller.

    The ISRs as written work fine when Event B and A are in tandem. The problem only occures when Event B occures at the same time. I'm not sure if event B is getting serviced in the middle of A. That is my hypothesis. As you can see I have placed code in there to disable Event B in case of ISR A execution.

    The longer interrupt (interrupt A) is the more important one. I am not sure if interrupt B is being serviced at the same time as interrupt A. This is difficult to debug because 1000s of event Bs are occuring and 100s of event A. Also, this doesn't fail on 1st simultaneous A+B event. It fails on the 3rd or 4th. I see the failure case in USB bus trace which shows the 2 events occuring.

  • The chip is EZUSB from Cypress semiconductor. The 8051 in there has some enhancements with a external vectored interrupt controller.
    If that had been included in the first post, maybe 2/3 of the effort many has made to help you would not have been wasted.

    Erik

  • EZUSB is not a number, unless they only have one chip in the family. I will look. Event B and A is that how they are referred to in the data sheet? You are giving very little to work with. Only people who have worked on that specific chip can help. I am not convinced you hypothesis is correct.

  • I looked at one of the EZ-USB chips. You have several options, you code snippet tells very little. Priority applies. Plus there is a second USB Interrupt priority there is a note about the proper order to clear the flags. USB is not on interrupt 0. There are 2 USB interrupts with several events.

  • Error prone or not - nested interrupts are quite common and can be very valuable for some hard-to-service hardware.

    It shouldn't be ignored just because it can fail - an incompetent programmer can manage to blow up a single "hello world". The problem isn't if the tools supports failing constructs, but of the developer allows the code to fail.

    If I decided to limit myself to totally "safe" development tools, I may have to switch to Logo. But I fear that my productivity would take a hit.

    A different - and somewhat (!) inflamed - thread discusses black or white or shades in between. This is yet another example of nuances. If I don't need nested interrupts, I avoid them. But I don't forbid myself from using them if I feel that they represent a real advantage.

    The question here is if the OP is in a situation where nested interrupts represent a real advantage, or if the wish for nested interrupts is based on a misconception that may bite even harder after a change to nested interrupts. Too quickly grabbing a heavier tool tends to result in far more dangerous accidents.

  • A different - and somewhat (!) inflamed - thread discusses black or white or shades in between. This is yet another example of nuances. If I don't need nested interrupts, I avoid them. But I don't forbid myself from using them if I feel that they represent a real advantage.
    nothing wrong with bested interrupts (I use them), but why all that hoolabaloo about doing it without using the intended tool: IP

    Erik