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?
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();
}
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.
Thanks for your comments. The problem turned out to be something very simple. Solution:
In Event B ISR, P_EPIRQ = 0x04; which clears the IRQ has to be done after EZUSB_IRQ_CLEAR(); which is the global IRQ. Otherwise unwanted nesting occures.
The question that no one answered was whether the IRQs generated by C51 are nestable. From above, apparently they are not since nesting causes immediate failure.
This is not a general 8052 question. This is an add-on that is specific to your Chip. The general 8052 rules do not fully apply.