failure to return from function?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

failure to return from function?

Jump to solution
1,642 Views
irob
Contributor V

Sorry for the lack of details in that subject line. I'm working with the MC9S08QG8 and have written a function to access external EEPROM and print to UART the results.  This function uses a local array of 14 bytes.  I have a local pointer to this array which I use to do the heavy lifting.  See below:

 

 

void RawMemory(void){  word addr = 0;  byte eeprom[PARAMETERS] = {0};      // EEPROM memory array  byte* eeprom_ptr = eeprom;          // pointer to array  NewLineChars();  SendString("Memory:"); NewLineChars();  do  {    i2c_error = I2CRandomRead(EEPROM_ADDR,addr,eeprom_ptr);    if (i2c_error)    {      i2c_clk_dly = I2C_CLK_DLY2;   // try slower I2C clocking speed and retry      addr = 0;      eeprom_ptr = eeprom;    // reset RAM array pointer      i2c_error = 0;    // reset flag    }    else if (*eeprom_ptr == BLANK_BYTE)    {      NewLineChars();      break;  // stop reporting once blank spot found    }    else    {      SendAscByte(*eeprom_ptr);      // report EEPROM value      TxChar(SPACE);    }    if (eeprom_ptr == eeprom + PARAMETERS)    {      CursorString();   // command line      eeprom_ptr = eeprom;    // reset RAM array pointer    }    else eeprom_ptr++;  } while (++addr < EEPROM_BUFF); // end while loop} // end RawMemory()

 

 

This function works as it should.  However, when returning from the function, the program "runs off into the weeds."  I've tried upping my stack pointer in the .prm file, as high as the compiler would let me.  No effect.

 

Assuming it was the size of the local array, I even tried a different approach with a single byte variable for 'eeprom'.  Still the same problem.

 

RAM problems have always been a bit mysterious to me in terms of troubleshooting.  Any recommendations?  Thanks!

Labels (1)
0 Kudos
Reply
1 Solution
1,082 Views
Lundin
Senior Contributor IV

May I suggest rewriting it into something like the following seemingly equivalent code?

 

 

 

BOOL RawMemory(void){  byte eeprom_val = 0;  word i;  BOOL result = TRUE;  NewLineChars();  SendString("Memory:");  NewLineChars();  for(i=0; i<EEPROM_BUFF; i++)  {    if(I2CRandomRead(EEPROM_ADDR, i, &eeprom_val) == FALSE)    {      result = FALSE;      break;    }    else if (eeprom_val == BLANK_BYTE)    {      NewLineChars();      break;  // stop reporting once blank spot found    }    else    {      SendAscByte(eeprom_val);      // report EEPROM value      TxChar(SPACE);    }        if (i == PARAMETERS)    {      CursorString();   // command line    }  }    return result;}

/* I2C_driver.c */
static Something i2C_error;

void I2CSlowDown (void)
{
  i2c_clk_dly = I2C_CLK_DLY2;  
  i2c_error = 0;
}

BOOL I2CRandomRead (...)
{
}



/* caller: */while (RawMemory() == FALSE){
  I2CSlowDown();
}

 

 

View solution in original post

0 Kudos
Reply
3 Replies
1,083 Views
Lundin
Senior Contributor IV

May I suggest rewriting it into something like the following seemingly equivalent code?

 

 

 

BOOL RawMemory(void){  byte eeprom_val = 0;  word i;  BOOL result = TRUE;  NewLineChars();  SendString("Memory:");  NewLineChars();  for(i=0; i<EEPROM_BUFF; i++)  {    if(I2CRandomRead(EEPROM_ADDR, i, &eeprom_val) == FALSE)    {      result = FALSE;      break;    }    else if (eeprom_val == BLANK_BYTE)    {      NewLineChars();      break;  // stop reporting once blank spot found    }    else    {      SendAscByte(eeprom_val);      // report EEPROM value      TxChar(SPACE);    }        if (i == PARAMETERS)    {      CursorString();   // command line    }  }    return result;}

/* I2C_driver.c */
static Something i2C_error;

void I2CSlowDown (void)
{
  i2c_clk_dly = I2C_CLK_DLY2;  
  i2c_error = 0;
}

BOOL I2CRandomRead (...)
{
}



/* caller: */while (RawMemory() == FALSE){
  I2CSlowDown();
}

 

 

0 Kudos
Reply
1,082 Views
irob
Contributor V

You guys were right.  I was incrementing my pointer too far.  Wow, didn't quite know that was possible, corrupting the RTS on the stack.  Makes sense now.

 

Lundin, I like your function edits.  I had to make one change for the CursorString call.  I wanted each multiple of PARAMETERS to output a newline and a cursor.  See below:

 

 

BOOL RawMemory(void)
{
  byte eeprom_val = 0;
  word i;
  BOOL result = TRUE;

  NewLineChars();
  SendString("Memory:");
  NewLineChars();

  for(i=0; i<EEPROM_BUFF; i++)
  {
    if(I2CRandomRead(EEPROM_ADDR, i, &eeprom_val) == FALSE)
    {
      result = FALSE;
      break;
    }
    else if (eeprom_val == BLANK_BYTE)
    {
      NewLineChars();
      break;  // stop reporting once blank spot found
    }
    else
    {
      SendAscByte(eeprom_val);      // report EEPROM value
      TxChar(SPACE);
    }
   
    if ((i+1) % PARAMETERS == 0) // is index at the end of a line?
    {
      CursorString();   // command line
    }
  }
 
  return result;
}

 

Works nicely.

 

0 Kudos
Reply
1,082 Views
rocco
Senior Contributor II

Hi Rob,

 

I think you are overwriting your function's return address.

 

If your "eeprom" array is PARAMETERS bytes long, then the last byte in the array is at "eeprom[PARAMETERS-1]", yet you are allowing the pointer to be incremented to  "eeprom + PARAMETERS", which is one byte outside the array.

 

I would think it would only corrupt the local variable "addr", but if "addr" is optimized off the stack then you would be corrupting the return address.

0 Kudos
Reply