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!
Solved! Go to Solution.
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(); }
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(); }
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.
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.