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

How to get data out of an interrupt?

Hi,

I would like to retrieve some value from my external interrupt handler. The external interrupt handler goes through different states and I would like to evaluate some value inside the interupt handler from outside the interrupt handler and also from another sourcefile/module.

I use (in the interrupt module):
volatile unsigned char myByte;

I use (in the evaluating module):
extern volatile unsigned char myByte;

In the module during evaluating of 'myByte' I disable the external interrupt.

But I still do not get the correct value.

Where do I go wrong?

Henk

  • The following bits of information would be helpful:

    1. Source code of ISR and the function that accesses the shared variable. Preferably stripped down to the minimum amount of code necessary to reproduce the behavior you observe.

    2. Which value do you expect to "get", and which value do you actually "get" ?

  • hi.

    what you have to do is return value from the interrupt.

    i have not book here but code is so.

    
    unsigned char external_interrupt(void) interrupt reentrant 12 using 3
    {
      int my_result;
    
      /* do something //
    
      my_result = 5;  // always fixed here
    
      return complex;
    }
    
    

    look in manual for more detail.

  • hi.

    sorry. i look again and not certain about reentrant situation.

    maybe someone help in this?

  • "what you have to do is return value from the interrupt"

    Absolutely not!

    There is no way to return anything from an interrupt fuction!

    Think about it: the ISR is called directly by the hardware - so how could it return anything?!

  • Accessing data-stores from within an isr should not be done in a simple assignment access. A data-store modifying interrupt could occur in the middle of the non-isr access to the data-store. A multi-byte data-store (aka "variable") like a 16-bit "int" on an 8-bit machine will force two reads from memory, and between those reads, the isr might modify the value. In your case, you are using an 8-bit variable in an 8-bit system so it shouldn't cause an error.

    I suspect that you are doing an extern to a data-store that is declared within the ISR function itself and not a data-store that is declared at the module level. (I would expect the compiler to error/warn you on that though).

    #include <stuff.h>
    int a;      // accessible using extern from another module
    
    void isr( void ) interrupt 1
    {
        int b;  // not accessible by another module
    
        ...
    }
    
    extern int a; // works
    extern int b; // shouldn't work: should be un-resolved at linker level
    

    Here is a couple of renditions to accessing isr variables. The first method reads the isr value over-and-over until a stable value is attained (or until a maximum iteration has occurred). This approach has its pitfalls, like two coincidental and identical miss-reads, but it does allow the interrupt process to be unobstructed.

    The second disables the interrupts so an un-interrupted access can be made: an atomic read. Many of the examples of this technique disable all interrupts, but you could just disable the particular interrupt source
    that affects the variable you desire to acquire and then re-enable it.

    /* ================= Data Type .H ========================= */
    
    typedef unsigned char  data_type;   // assign as required
    
    /* ================= The ISR Module ======================= */
    
    volatile data_type myByte;      // Allocate the variabl... module-scope'd
                                    // (not within the isr function)
    
    void isr( void ) interrupt 151  // select your interrupt routine
    {
     /* volatile data_type myByte;  // NOT 'extern'-able FROM HERE */
        myByte++;
    
        Do_What_Ever_Needs_To_Get_Done( ); // make this short-n-sweet
    }
    
    
    /* ================= Non-ISR Module ======================= */
    
    #define MAX_TRIES   10 // pick the quantity of attempts
    
    extern volatile data_type myByte; // ref the data store
    
    /* -------------------------------------------------------- */
    /* Accessing an ISR modified data store (two methods)       */
    /* (especially for non-atomic accesses to the data type)    */
    /* -------------------------------------------------------- */
    data_type Get_ISR_Value( bit method ) // { (ONE=1) | (TWO=0) }
    {
        unsigned char   tries;  // safety escape counter
        data_type       val;    // return value
    
        /* -------------------- METHOD 1 -------------------- */
        /*                                                    */
        /*  Allows ISRs to be continueously serviced          */
        /*                                                    */
        if( method != 0 )
        {
            tries = 0;
    
            while(    ((val=myByte) != myByte ) // keep reading until stable
                   && ( tries < MAX_TRIES     ) // stop if we tried too much
            )
            {
                tries++;    // bump the safety escape counter
            }
    
            if( tries >= MAX_TRIES ) // handle the timed-out case
            {
                Freak_Out( ); // Stick in some error handler code
                val = 0;      // null it out
            }
        }
        else
        /* -------------------- METHOD 2 -------------------- */
        /*                                                    */
        /*  Stops all ISRs from being serviced... (could just */
        /*  disable the specific isr which modifies the data  */
        /*  store and then re-enabling it after the access is */
        /*  performed)                                        */
        /*                                                    */
        {
            EA  = DISABLED; // block interrupts (a forced atomic access)
    
            val = myByte;   // grab a copy of the data
    
            EA  = ENABLED;  // enable interrupts
        }
    
        return( val );
    }
    
    /* ================= Simple Main Module =================== */
    
    #define FOREVER 0xC5 // lotsa bits are non-zero, and not just 1 of them
    
    extern data_type Get_ISR_Value( bit );
    
    void main( void ) // example
    {
        data_type   new;
        data_type   old;
    
        new = 0;
        old = new;
    
        while( FOREVER ) // implied "!= 0"
        {
            new = Get_ISR_Value( 1 );
    
            if( new != old )
            {
                printf("\n New ISR state = %d", new ); // never use 'printf'
            }
            old = new;
        }
    }
    

    --Cpt. Vince Foster
    c/o VRWC (founding member)
    2nd Cannon Place
    Fort Marcy Park, VA

  • typedef unsigned char  data_type;   // assign as required
    

    Not So fast.

    If the global is a char or bit your code is OK. But if is an int or larger it will not be atomic for an 8052. The main() functions would have to disable interrupts or take other action to insure proper operation.

  • The typedef statement still applies regardless of the data size chosen: the code will work with more than 1-bit or 8-bits... like a long, etc. (please re-read the post)

    --Cpt. Vince Foster
    c/o VRWC (founding member)
    2nd Cannon Place
    Fort Marcy Park, VA