Need feedback on Wear leveling code
lardom
Posts: 1,659
I'm trying to come up with a way to write to my eeprom so it lasts longer so I wrote some pseudo code to look for obvious flaws in my logic. I want to use array variables for the five programmable variables in my project. The following code will not run. My purpose is to get feedback from experienced programmers. If it makes sense I will write a second method that reads the value-containing element.
The idea is for one array element at a time to contain a value. It will require two operations on a physical address per loop. One will erase and the other will write.
The idea is for one array element at a time to contain a value. It will require two operations on a physical address per loop. One will erase and the other will write.
PUB Pseudo_Code | ptr if distance[ptr] > 10 distance[1] := Some_Data repeat until distance[ptr] <> 0 distance[ptr] := distance[ptr]++ distance[ptr] := 0 EEPROM := distance[ptr] distance[ptr] := distance[ptr]++ distance[ptr] := Some_Data EEPROM := distance[ptr]
Comments
Your code is very confusing and just doesn't make sense. I think you're confusing the use of ptr with distance[ptr]. How about just carefully describing what you're trying to accomplish at each step?
I also attached a graphic to illustrate my idea.
I think you're unnecessarily complicating what you want to do.
You don't say what range of values you want to store. Maybe you need one byte per value, maybe you need four. It isn't clear.
You need some way to tell where the data begins and ends in the EEPROM and this needs to be part of the data. One easy way is to use an odd number of bytes or words and to set aside a single bit in each byte or word that gets toggled for each value. With an odd number of entries, there will always be two adjacent entries with the same bit and all the other pairs of entries will have opposite bit values. The only time this won't be true is during the first use of the EEPROM area and that can be addressed by initializing the area.
When you start up your program, the EEPROM area gets searched for the first pair of entries with the same marker bit. The first of the pair is the last entry stored and the second of the pair is the oldest entry in the EEPROM area and the next to be overwritten.
All of the values are word sized. [ptr++] <-- That was helpful. I had planned to use a prewritten object to write to the eeprom but I see now that it is essential that I understand the process myself.
(I have yet to understand why the address of an eeprom is $A0.) You are the best. Thanks.
The address of the EEPROM is $A0 because of the way the select byte is arranged. Look at the datasheet for any I2C EEPROM and you'll see a diagram that shows how the bits of the select byte are allocated and it should be obvious why the address is the way it is.
In your EEPROM object you will have a routine that reads bytes and a routine that writes them. In the i2cdemoapp these are:
i2cObject.WriteLong(i2cSCL, EEPROMAddr, eepromLocation, eepromData)
eepromData := i2cObject.ReadLong(i2cSCL, EEPROMAddr, eepromLocation)
Your basic strategy is this. First, determine a range of EEPROM addresses you want to use; if you have a 64K eeprom such as on a proto- or demoboard, you can start at $8000 and ignore application downloads. And the more EEPROM you decide to use the slower you'll wear it out, but the more EEPROM you'll need.
Your strategy:
Start at the base of your range and search for a non-all-ones entry. (All 1's is blank EEPROM. This scheme depends on that not being a valid value; you might need to assign an always-zero marker byte or bit to make sure this is the case.)
If you find a non-all-ones entry, write ones to it to clear it and advance your counter to the next entry beyond it. If you advance past the end of your range, set it to the start of your range. Now write the new value at the pointer.
If you don't find a non-all-ones entry, just start at the beginning of your range.
If you are updating often you can remember the pointer instead of searching for it on subsequent updates. You really only need to do the search on power-up.
This gives you averaged out wear without the problem of updating a pointer that will itself wear out at full speed.