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
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.
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)
Yes it does. My mistake