View previous topic :: View next topic |
Author |
Message |
Wilksey
Joined: 14 Aug 2011 Posts: 36 Location: Somerset, UK
|
EEPROM read anomaly |
Posted: Thu Nov 09, 2023 2:57 pm |
|
|
Hi,
I have a 18f4550 connected to a i2c 2404 E2PROM, I can write to the chip and read it back in a different reader and it gives me the same bytes as I programmed in followed by ff's, there are 28 bytes written and the rest are ff's which is right.
When I try and read it back with CCS C I go through a loop reading the bytes until it reaches 0xFF, using the internal E2PROM it works, with the external it reads it, but byte 29 onwards which is 0xff it just carries on and fills the buffer up with ff's, any idea what the problem is? I m using the CCS C driver and here is my section of code:
Code: |
BYTE loaded_code[512] = {};
EEPROM_ADDRESS number_of_lines = 0x00;
while (loaded_code[number_of_lines] != 0xFF)
{
loaded_code[number_of_lines] = read_ext_eeprom (number_of_lines);
number_of_lines++;
} |
Any suggestions greatly appreciated!
TIA |
|
|
gaugeguy
Joined: 05 Apr 2011 Posts: 303
|
|
Posted: Thu Nov 09, 2023 3:30 pm |
|
|
Your while loop is testing the array location before you read a byte into it from the external eeprom. |
|
|
Wilksey
Joined: 14 Aug 2011 Posts: 36 Location: Somerset, UK
|
|
Posted: Thu Nov 09, 2023 3:46 pm |
|
|
the array is all 0's before the loop starts, so it would only read 0xff from within the loop after it has read the E2PROM.
This code works:
Code: |
for(number_of_lines = 0; number_of_lines < EEPROM_SIZE; number_of_lines++){
loaded_code[number_of_lines] = read_ext_eeprom(number_of_lines);
if(loaded_code[number_of_lines] == 0xff) {
break;
}
}
|
Why is that any different to the while loop? |
|
|
gaugeguy
Joined: 05 Apr 2011 Posts: 303
|
|
Posted: Thu Nov 09, 2023 4:00 pm |
|
|
Look through the code carefully. Write down the value of number_of_lines as well as the value of loaded_code[number_of_lines] at each step. |
|
|
Wilksey
Joined: 14 Aug 2011 Posts: 36 Location: Somerset, UK
|
|
Posted: Thu Nov 09, 2023 4:32 pm |
|
|
Going back to the old code, number_of_lines goes from 0 to 511 then 767 to 985 for some reason but the data is correct it just doeesn't stop at byte 29 which s 0xff, the for loop goes from 0 to 28 which is correct as byte 29 is 0xff. And the bytes both look the same up to byte 29 then it becomes FF's.
I know I am missing something simple, but I can't see the wood for the trees |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9246 Location: Greensville,Ontario
|
|
Posted: Thu Nov 09, 2023 5:27 pm |
|
|
1st guess was 'number_of_lines' is defined as a byte, but that'd be 0-255, you've magically got 0-511,then a jump to 767....
yeesh
I recall some 'function' called 'hi(x)=....' posted 1-2 weeks ago that correctly decodes eeprom address into the 2 bytes need to access eeprom data.
Maybe something like that is happening ??
Jay |
|
|
Wilksey
Joined: 14 Aug 2011 Posts: 36 Location: Somerset, UK
|
|
Posted: Fri Nov 10, 2023 4:12 am |
|
|
number_of_lines is defined as EEPROM_ADDRESS, and for 2404 it is a long int,
The fix was to move the variable increment to the top before the assignment.
Code: | while (loaded_code[number_of_lines] != 0xFF)
{
number_of_lines++;
loaded_code[number_of_lines] = read_ext_eeprom (number_of_lines);
} |
I'm not really sure why that works because it starts at index 0 unless the read_ext_eeprom needs to discard the first byte? |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9246 Location: Greensville,Ontario
|
|
Posted: Fri Nov 10, 2023 5:57 am |
|
|
curious for sure, but I'd have to see the whole program to 'play computer' to see what's happening.
eeprom address variable should be 'unsigned' though compiler may default 'int' to 'unsigned'.
pretty sure the eeprom can't have memory location -23 though at my age, I don't have all my memory cells anymore, |
|
|
Wilksey
Joined: 14 Aug 2011 Posts: 36 Location: Somerset, UK
|
|
Posted: Fri Nov 10, 2023 7:24 am |
|
|
Yesh that's what I thought but the int long came from ccs c driver folder, , changing it to unsigned remains the same, maybe it's because it's only 512? |
|
|
gaugeguy
Joined: 05 Apr 2011 Posts: 303
|
|
Posted: Fri Nov 10, 2023 7:28 am |
|
|
While your "fix" does allow it to stop the loop when 0xFF is read, it also results in loaded_code[0] never getting a value stored into it.
Take a piece of paper and write down the value of the variables at each step through the loop to see what is actually happening. |
|
|
Wilksey
Joined: 14 Aug 2011 Posts: 36 Location: Somerset, UK
|
|
Posted: Fri Nov 10, 2023 8:20 am |
|
|
I can get around it by reverting to for loop or setting the variable to -1, which seems to work |
|
|
gaugeguy
Joined: 05 Apr 2011 Posts: 303
|
|
Posted: Fri Nov 10, 2023 8:38 am |
|
|
if starting at -1
Your first test will be (loaded_code[-1] != 0xFF)
do you know what is at loaded_code[-1] ?
I think you need to study the difference between a while loop and a do-while loop. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Fri Nov 10, 2023 8:51 am |
|
|
Remember integers in CCS by default are unsigned....
-1 = 255 |
|
|
Wilksey
Joined: 14 Aug 2011 Posts: 36 Location: Somerset, UK
|
|
Posted: Fri Nov 10, 2023 8:51 am |
|
|
It increments before it reads so in reality it always reads x[0], with the for loop I can set it explicitly to 0, do while didn't work either until I put the increment above, very odd, never had that before with my other C compilers.
There is no loaded-code[-1], it is unsigned so it will presumably enter unknown space |
|
|
gaugeguy
Joined: 05 Apr 2011 Posts: 303
|
|
Posted: Fri Nov 10, 2023 10:09 am |
|
|
You are using a while loop, not a do-while loop. There is a difference.
Lets unroll your original code:
BYTE loaded_code[512] = {};
EEPROM_ADDRESS number_of_lines = 0x00;
while (loaded_code[number_of_lines] != 0xFF)
{
loaded_code[number_of_lines] = read_ext_eeprom (number_of_lines);
number_of_lines++;
}
number_of_lines = 0x00
while(loaded_code[0] != 0xFF) // not set to anything yet so at init value 0
{
loaded_code[0] = read_ext_eeprom(0); // value loaded from eeprom
number_of_lines++; // now 1
}
while(loaded_code[1] != 0xFF) // not set to anything yet so at init value 0
{
loaded_code[1] = read_ext_eeprom(1); // value loaded from eeprom
number_of_lines++; // now 2
}
while(loaded_code[2] != 0xFF) // not set to anything yet so at init value 0
{
loaded_code[2] = read_ext_eeprom(2); // value loaded from eeprom
number_of_lines++; // now 3
}
...
Can you now see why your original code cannot work the way you expect in any version of C? |
|
|
|