I'm using Keil compiler for 8051Warp uP. I would like to make a jump from an interrupt routine back to the main function, this way: main () { init_function(); if (setjmp(env)!=0) { // Recovery procedure here ... } while (1) { // body of my program ... } } void irq (void) interrupt (12) { if (condition) longjmp (env,1); } void init_function() { IE = 0xA0; IEN1 = 0xC4; IP = 0x00; IP1= 0x40; } I'm experiencing the following problem. Right after the longjmp instruction, the execution actually restarts at the setjmp instruction point (as i wish), but no more interrupt can be serviced after this jump. It looks like the IE.7 bit has been reset in some way. Anyway, even if i set the IE / IE1 registers after the jump, no more interrupt are serviced by the uP. Somebody could help me? Thanx.
The 8051 since the dawn of time has had two levels of interrupt priority. Any RETI from either level to address 0x0000 will reset the processor with the interrupt system enabled. Only one RETI should be needed unless I'm missing something. E.g. If a low priority ISR executes a RETI with 0x0000 on the stack for a return address then by definition there is no high priority ISR executing. It would be wise to clear IE before the RETI of course. By corallary, if a high priority ISR executes a RETI with 0x0000 on the stack for a return address then by definition there is no low priority ISR executing at that particular moment. Again, clear IE before the RETI.
...if a high priority ISR executes a RETI with 0x0000 on the stack for a return address then by definition there is no low priority ISR executing at that particular moment. I don't understand. My Philips datasheet seems quite clear about this "A low-priority interrupt can itself be interrupted by a high-priority interrupt, but not by another low-priority interrupt." Besides, I know that this is exactly what happens from experience. Also, I am not aware that 0x0000 on the stack has any special meaning to the processor - you may be right, but I cannot find anything in the datasheets. Personally, I have always used a timed-out watchdog to effect a real reset, but I am certainly curious to get to the bottom of this issue.
I don't understand. My Philips datasheet seems quite clear about this "A low-priority interrupt can itself be interrupted by a high-priority interrupt, but not by another low-priority interrupt." Besides, I know that this is exactly what happens from experience. This is quite accurate. However, it says nothing about re-enabling the interrupt subsystem when jumping to 0x0000. If you jump to 0x0000 from main line code (not from any ISR) the processor will reset and run properly. If you jump to 0x0000 from a low priority ISR the processor will reset but interrupts will be permanently disabled. You must indicate to the processor that the ISR has been handled via a single RETI, not two. From a high priority ISR you probably have to RETI to some stub code that executes another RETI after setting the return address to 0x0000. I guess a double RETI when only a single high priority ISR has fired (e.g. no preempted low priority ISR's) would work okay. Just make you life simple and either reset from a low priority ISR or from the main line code. Also, I am not aware that 0x0000 on the stack has any special meaning to the processor - you may be right, but I cannot find anything in the datasheets. 0x0000 on the stack is very important when you do a RETI or RET because this is the address the processor will return to. Thus, putting 0x0000 on the top of the stack and issuing a RETI (RET from main line code) will cause the processor to properly reset. Personally, I have always used a timed-out watchdog to effect a real reset, but I am certainly curious to get to the bottom of this issue. A watchdog reset is a far simpler and sure way to reset any processor of course.