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

Strange Interrupt leads to Abort Mode

I've got a unexpected problem with Interrupts.
Would be nice to discuss it.

I use Timer0 to have about 16000 fast interrupts (FIQ) per second.
There is a AD-Conversation and a few lines of long long int aritmetic to compute. Inside this FIQ-routine there is a static counter. When it reaches 16000 it is reseted and a Software interrupt (SWI) is generated every second.

The SWI-routine has do to some computations and then to display it all on a special three wire conected display.

The programm does not work with 16000 Timer0 Interrupts per second.
It is terminated by Abort-Mode. This comes a little unexpected to my. The effect is gone if i turn down FIQ frequency downto 100Hz. Is it possible that interrupts create a stack overflow?

Should i post my code?

Parents
  • hi Per and everyone else,
    thanks for your kind reply.
    There is no more information that i can give about my little project, just the code to initialize Timer and interrupt. At this time, the Main programm is just like

    int main(void)
    {
        init_ADC();
        Timer_0_init();
        interrupt_init();
        while(1) {} //now endlessloop, but later important stuff
    }
    //*************************************************************************
    void Timer_0_init(void)
    {
            T0LD  = 1632 - 1;
            T0CON = 0xC8;           // Enabled,Periodic,Clock/256
    }
    //*************************************************************************
    void interrupt_init(void)
    {
        FIQEN = RTOS_TIMER_BIT; // Timer_0
        IRQEN = SWI_BIT;
    }
    //*************************************************************************
    


    My idea when i wrote this was, the Timer_0 calls FIQ 16000 times per second. Inside FIQ there is a routine that makes a IRQ call every second. The IRQ drives the 3-wire-display, it can and should be interrupted by FIQ. I have no idea what this SVC-Mode is, maybe i have to read the whole DDI0029G ARM7TDMI Technical Reference Manual and DDI0100E ARM Architekture Reference Manual? I'am afraid of doing this!

Reply
  • hi Per and everyone else,
    thanks for your kind reply.
    There is no more information that i can give about my little project, just the code to initialize Timer and interrupt. At this time, the Main programm is just like

    int main(void)
    {
        init_ADC();
        Timer_0_init();
        interrupt_init();
        while(1) {} //now endlessloop, but later important stuff
    }
    //*************************************************************************
    void Timer_0_init(void)
    {
            T0LD  = 1632 - 1;
            T0CON = 0xC8;           // Enabled,Periodic,Clock/256
    }
    //*************************************************************************
    void interrupt_init(void)
    {
        FIQEN = RTOS_TIMER_BIT; // Timer_0
        IRQEN = SWI_BIT;
    }
    //*************************************************************************
    


    My idea when i wrote this was, the Timer_0 calls FIQ 16000 times per second. Inside FIQ there is a routine that makes a IRQ call every second. The IRQ drives the 3-wire-display, it can and should be interrupted by FIQ. I have no idea what this SVC-Mode is, maybe i have to read the whole DDI0029G ARM7TDMI Technical Reference Manual and DDI0100E ARM Architekture Reference Manual? I'am afraid of doing this!

Children
  • Sorry, the code i posted is the actual version.
    The main clock frequency is 32768 * 1275 = 41779200 Hz.
    The Timer_0 prescaler makes a division by 256 (41779200 / 256 = 163200).
    So a T0LD register value of "1632" leads to a 100Hz interrupt frequency. At this rate, there is no "running into Abort-Mode-Problem". But my goal was to have an average with 16000 ADC-samples.

    SOS need further assistant urgently ;-)

  • George,
    your

    ACC3_transfer
    

    is not interrupt safe. You would need to disable IRQ and FIQ when working with it.

  • My recommendation is to have the FIQ copy the relevant data once/second and then have the main loop - or a dedicated task - perform the display output. A three-wire interface to the display means that it will take somewhile to output the data. Leave that to the main loop.

    Have you measured how long it take to emit the data to the display?

    Have you measured how large % of your CPU power that is consumed just by the FIQ when running 16kHz? All time lost to the FIQ is extra calendar time needed for the display output unless you can issue a single transfer to the display and then let the hw handle all output.

    You mention SWI. By that, I assumed that you meant the specific instruction used to enter the SVC mode. This is normally done by declaring functions like:

    void __swi(0) my_handler(params);
    void __SWI_0            (params) {
        ...
    }
    

    But I see now that you instead mean that you manaully assert a normal interrupt, and let the processor enter this interrupt as soon as it leaves the FIQ handler.

    Then no SVC mode will be involved. However, have you made sure that the IRQ stack is large enough to support the printf() call?

    Another thing: You start an ADC conversion in the FIQ handler, and then spend time waiting for the answer. Don't do that. Get the existing ADC value and then start a new transfer. Then the interval between the FIQ interrupts will be used for the conversion. 16000 times the dummy wait for a conversion is just lost CPU power - potentially more CPU power than you have...

    Tamir: The transfer should not need to be interrupt-safe. The FIQ only performs the update once/second, and then issues a request to activate the reader. As long as the reader - the display output code - is guaranteed to finish within one second of being trigged, there should be no need for extra protection.

  • Per,
    you are right. I built my own scenario based on the text description, rather than to look carefully at the code.

  • Thanks you all for your help. :-)
    At this time my modified code works.
    I cannceled this SWI-stuff.
    I just put the 3-wire-display in the main-loop.
    The FIQ-routine sets a flag after 16384 ADC-samplings.
    The main-routine watches this flag, does a 3-wire-display-output and resets the flag.

  • char text[10];
    
    sprintf(text,"%8.d",(D3 * 125) >> 27);
    
    static long long unsigned int ACC3D,D1,D2,D3,D1D,D2D;
    

    George, remember that "%8.d" is a minimum width specifier, not a maximum and that D3 is a 64 bit integer that is probably increasing in value with the number of FIQs.

    A 64 bit integer is then being shifted right by 27 bits before being passed to sprintf (who is probably looking at it as a 32 bit integer but it can be still big enough to cause an overflow in your 10 character buffer).

    I'd guess would be that you will get a pre-fetch abort when sprintf tries to return to IRQ_Handler because the buffer overflow on "text" trashes the LR that sprintf pushed to the stack.