We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
I have a situation where code runs fine at one setting and not at anther. At issue are two timer routines. Both are low priority. sThey are timer 2 and timer 3 in a Silabs 040 processor. The PCA is the high priority interrupt. Timer 2 interrupt is used to feed sinewave table to DAC to generate a sine wave. Timer 3 is the system 10 ms heartbeat. if the PCA (which is used to generate pulses) is generating a pules shorter than 8 cycles at 1 mhz, AND it is time for a sound, the sound happens, but the flag to end the sound (which is cleared in the timer 3 routine) never gets cleared, and the ssound runs forever. If you break the code with the debugger, you find that timer 3 has timed out and is requesting an interrupt. IF you change timer 3 priority to high, it will run and the signal will cease, but the pulse train from the PCA will be messed up. I've already addressed that,by making everything else low priority.
NOW: There is one way out of this, and that is to check at the bottom of the timer 2 interrupt, to see if there is a timer 3 interrupt pending, and transfer control to the timer 3 interrupt. This will work because both interrupts push and pop the same parameters off the stack.
The question is how to do this in C without resorting to an assembly instruction, which results in the compiler emitting assembly code, and you having to assemble it separately. This is not acceptable in my complex build process.
((unsigned car (code*)(void)) Timer_3_vector)(); ((void (code*)(void)) Timer_3_vector) ();
results in a CALL which messes up the stack. I don't have enough space to do this in the stack.
I just need to find a way to do a jump directly to the timer 3 interrupt routine. setjump/longjump doesn't work in this case.
Goto only works within a subroutine. AND DON'T tell me this is bad programming practice. I know that full well. This is a well controlled embedded system, so I can get by with something like this, though it makes my skin crawl to think about so doing.
Any ideas?
Can you get away with temporarily boosting its priority at the point you want it to run, then reduce the priority at the beginning of the timer 3 ISR to allow the PCA to interrupt again?
Hmm. might work. hadn't thought a about that one. But I think it would probably cause PCA pulses to get messed up, which won't work.
I wanted to avoid the stack usage of a function call. But I finally crafted this solution:
Problem. A lowlevel interrupt has locked another low level interrupt out (Timer 2 is higher in the vector table than timer 3 so takes precedence.) in Timer 2 I tested the timer 3 interrupt pending bit and then call this routine, which cleans up the stack and vectors to timer 3. problem solved. no more low level priority lockout. This technique can be extended to any priority lockout.
NAME vjump ?PR?GOTO_TMR3?vjump SEGMENT code PUBLIC GOTO_TMR3 rseg ?PR?GOTO_TMR3?vjumP ; ; designed to be called from within interrupt 2 to transfer to int 3 ; ; when this is called ACC can be trashed ; GOTO_TMR3: pop ACC ; clear the return address off the stack pop ACC POP PSW ; clear off interrupt stored data POP DPL POP DPH POP B POP ACC ; ; leave reurn address on the stack. Then jump to interrupt handler with interrupt status set, so that ; timer 3 interrupt will work as if it was started by an interrupt ; LJMP 0x0073 ;go to timer 3 interrupt handler END