Thank you, Raphael. your answer is very appreciated. I have refactored the code as you told, I put all the global variables in a header file, called "defs.h". I have also taken out all the calls to functions from the interrupt. Now, interrupt handler routine is a lot simpler. Just one thing: I haven't been able to disable the interrupt and save the stack with the code you gave me. Apparently, it should work, since I'm using a PIC 16F877, which seems to have 16 stack bytes. Am I missing something from your explanation?
BTW, I attach you the new code. Thank you again. On Sun, May 10, 2009 at 9:03 PM, Raphael Neider <rnei...@web.de> wrote: > Dear Néstor, > >> I'm running into trouble (once more) when executing my app. I attach >> the code so you can see. > > Your code is too complex to effectively debug it without the hardware, so > I can just contribute some ideas: > > You modify totaltime[] both within Intr() and outside it without > protecting it (e.g., by disabling interrupts while updating it); this may > lead to inconsistently setup data but should not cause the problem at hand. > >> The problem arises from my interrupt, which is calling some functions >> outside of it. It almost works, I explain myself: > > Calling functions from within the interrupt handler is broken, because > this would overwrite the STK00 .. STK0F (pseudo stack in sharebank) > without saving the interrupted state. If you disable interrupts globally > after entering the interrupt handler (to avoid nested interrupts), you can > save the pseudo stack manually like > > #define disable_interrupts(x) do { x = (INTCON & 0xC0); INTCON &= 0x3F; } > while (0) > #define enable_interrupts(x) do { INTCON |= x; } while (0) > > void Intr(void) __interrupt(0) { > unsigned char u; > unsigned char int_state; > char int_stack[16]; > > disable_interrupts(int_state); > for (u = 0; u < 16; u++) { > int_stack[u] = *(__data char *)(0x70 + u); > } > > /* handler code */ > > out: > for (u = 0; u < 16; u++) { > *(__data char *)(0x70 + u) = int_stack[u]; > } > enable_interrupts(int_state); > } > > (the above code is untested and target device dependent). > You will also have to replace all return statements in the handler code > with goto out; to restore the interrupted stack. > This is a compiler bug that should be addressed once I find the time ... > likely not very soon, sorry. > > > You should also consider replacing multiplication by 2, 4, or 8 with shift > operations, as the compiler does not optimize these cases (yet). If you > use *4, the compiler will call a support routine to perform the > multiplication --- which will corrupt the interrupted function's stack. > > Furthermore, you have static variable definitions (not declarations!) in > your temete4.h: addressH, addressL, menu_option, selected_item, treatment, > power, spot_time, and sound will all be instantiated in every .c (and .o) > file that includes temete4.h (i.e., temete[134].c). This wastes memory and > leads to unexpected behaviour if you access the variable in more than one > source file: these variables are not shared among the .c files, each one > gets its own copy -- and the linker won't tell you, because the linker > symbols are made file-local due to the use of static. > > You really should declare all shared functions and variables in a .h file > (using the extern keyword) and implement/define them in the according .c > file. The current state with repeated declarations in the .c files leads > to errors that the compiler cannot even warn about: As an example, > count_down is defined as volatile BYTE count_down[2] in temete1.c but > declared as non-volatile BYTE count_down[2] in temete3.c. Luckily for you, > temete3.c does not access the variable at all ... > > You often use the volatile keyword on function arguments. Though this is > possible, it is not often useful as the arguments are passed by value and > not by reference: the callee gets its own copy of the values passed to him > at the time of the call. Passing pointers to volatile data requires the > volatile keyword (as in volatile char *ptr), marking the arguments > themselves volatile (as in volatile char c or char * volatile ptr) only > leads to complicated/slow code being generated. > > > To aid in debugging, reduce the interrupt routine to as little as possible > while still showing bogus behaviour to rule out race conditions on shared > variables. > >> This application shows a menu with some options on screen, so you can >> select between them with an encoder. This encoder is read by the >> temete2.c:testEncoder() function, which enters a loop and uses global >> variable BYTE encoderStatus and local BYTE key[2] to put the old and >> both old and new encoder values, respectively. These values are taken >> from some input gates (specifically, from RC6, RD3, RD2). These input >> gates are only used for this purpose, and connected to the output of >> the encoder. And they are only called from this function, nowhere >> else. I have checked it throughfully. Some gates from PORTD are called >> from other places, but not Gates 2 nor 3. And TRISD is only used once, >> and switched to '0x0c' (So RD2, RD3 are inputs, the others are all >> outputs). >> >> Well, for the other side, we have a countdown, which draws some >> numbers on LCD screen via software I2C. To achieve this, I have >> written an interrupt, called temete1c:Intr(), which calls some >> functions to draw these values (temete4.c:PaintChar(), for example). >> Then, PaintChar calls other functions, until the low-level ones are >> reached. >> >> The problem is that I have observed that this interrupt actually >> modifies RD2's value, always to the opposite. So, while the >> testEncoder loop is running, key[] (and maybe the encoderStatus) >> variable is magically changed, like if the encoder was pressed. So, a >> menu option gets selected each time the clock is updated, and then, it >> gets unselected again. I'm speaking without the user actually pressing >> the encoder. I have observed no other strange behaviour, only this. It >> does not change RD3's value, indeed, which is very very curious. > > Does RD2 change in fact or does only key[] change? Can you print the > values of key[] and PORTD to find out? Does this happen even with an empty > interrupt handler? Does it suffice to call PaintChar from within the > handler to corrupt your data? > >> Am I incorrectly calling these functions from my interrupt? Have I >> made some other mistake? I think it's not possible to put all the code >> directly inside the interrupt, it's just too big, too repetitive. It's >> better put in a function. But it seems not to work 100%. > > As indicated above, the call stack STK* is garbled when function are > called from within the interrupt handler. If you protect the stack with > the code given above, this should be no problem. > > Good luck, > Raphael > > ------------------------------------------------------------------------------ > The NEW KODAK i700 Series Scanners deliver under ANY circumstances! Your > production scanning environment may not be a perfect world - but thanks to > Kodak, there's a perfect scanner to get the job done! With the NEW KODAK i700 > Series Scanner you'll get full speed at 300 dpi even with all image > processing features enabled. http://p.sf.net/sfu/kodak-com > _______________________________________________ > Sdcc-user mailing list > Sdcc-user@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/sdcc-user > -- Ricardo L. Febrero
temete-0.2.1.tar.gz
Description: GNU Zip compressed data
------------------------------------------------------------------------------ The NEW KODAK i700 Series Scanners deliver under ANY circumstances! Your production scanning environment may not be a perfect world - but thanks to Kodak, there's a perfect scanner to get the job done! With the NEW KODAK i700 Series Scanner you'll get full speed at 300 dpi even with all image processing features enabled. http://p.sf.net/sfu/kodak-com
_______________________________________________ Sdcc-user mailing list Sdcc-user@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/sdcc-user