I'm no computing wiz but I've found that if you use a
global variable as your check value in a while loop in a
function, then call another function within loop that
changes the value of the global variable, the check value
of the original while loop remains the same! This is due
to the fact that the assembly code generated pushes
the value of the global variable into a register at start of
function and then uses that value throughout the function
without ever updating it after nested function calls that
may or may not change value of specified global
variable. This to me seems like a major flaw since global
variables can no longer be used as parameters in loops
without extreme caution. I found some sdcc parameter
called --noinduction which seemed according to the
sdcc user guide to possibly solve the problem in
question but result turned out the same. Now, is this
supposed to work like this or are there any options to
force compiler to update registers of global variables
after all / some function calls within loops?
Help is much appreciated, need answer asap since I'm
working with a final year project and have a deadline to
keep!
Logged In: YES
user_id=306209
I have the same problem. The work-around appears to be to
assign the loop check value to be "xdata" and then use
--noinduction. This worked in my case.
Good luck.
Dave
Logged In: YES
user_id=203539
Please provide a short source snippet, so that we can
reproduce the problem.
Logged In: YES
user_id=306209
Here's a code snippet. Looking at the assembly, the loopCnt
variable is overwritten during the subroutine but never restored
before it is checked again. Let me know if you need anything
else. SDCC version is:
SDCC : mcs51/gbz80/z80/avr/ds390/pic14/TININative/xa51
0.0.0 (Mar 27 2003) (CYGWIN)
xdata at 0xE678 unsigned char I2CS;
xdata at 0xE679 unsigned char I2DAT;
xdata at 0xE67A unsigned char I2CTL;
int i2cRead( unsigned char cntlByte,
unsigned char byteCnt,
unsigned char *myData)
{
unsigned char i;
unsigned char loopCnt; /* xdata needed due 2 loop check
compiler bug*/
unsigned char temp;
I2CS |= START;
I2DAT = cntlByte;
while( !(I2CS & DONE) );
if((I2CS & BERR) || ( !(I2CS & ACK) ) )
{
if( I2CS & BERR )
myPrStr("BERR on I2C bus");
else
myPrStr("No ACK on I2C bus");
I2CS |= STOP;
return(-1);
}
loopCnt = byteCnt+1;
for( i = 0; i < loopCnt; i++) /* plus 1 because 1st rd undef*/
{
if( i == (byteCnt - 1))
{
I2CS |= LASTRD;
}
if( i == 0)
{
temp = I2DAT;
}
else
{
if( i == byteCnt )
{
I2CS |= STOP;
}
temp = I2DAT;
LEDPORT = temp;
*myData++ = temp;
}
if( i != byteCnt )
{
while( !(I2CS & DONE) );
/*
myPrStr("Waiting for DONE 3");
*/
if((I2CS & BERR) )
{
myPrStr("BERR on I2C bus");
I2CS |= STOP;
return(-1);
}
}
}
return(0);
}
Logged In: YES
user_id=203539
Unfortunately there's a life-range bug in SDCC, which is very difficult
to fix. A (untested) workaround for this problem is:
volatile unsigned char loopCnt;
Logged In: YES
user_id=635249
The gcse bug in the initial report has probably been fixed
by the updates noted in ChangeLog 1.514 and 1.506, but no
source code was posted to absolutely verify this.
The follow-up posted by dduxstad seems unrelated to the
original bug and instead a live-range problem that is likely
fixed by Klaus's new code (see ChangeLog 1.445 and later)