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

priority problem

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?

Parents Reply Children
  • 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