EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

Help needed storing array in EEPROM

Started by Simplymail March 26, 2005

I'm using this board:

http://www.axman.com/education/edc_hc12.html

a DS1305, hall sensor, LCD, Keypad.

Compiled with GNU for 68HC11 & 68HC12
EmbeddedGNU

The data collected from the hall is time stamped, and
two different arrays are created - one with 23 rows (for every hour of the day, military
time), and one for an entire year. The board works, outputs the two arrays to the serial
port. Yea.

I'd like to now store just the yearly array to EEPROM, and read it on startup (with the option
of erasing the memory). Is this easily possible? The code is in C, not assembly. Would it be
easier to just make a backup power supply?

Anyhow, I read both tech notes (AN2400/D, AN2302/D), and somewhat understand what
they are saying. I'm not an EE (but trying!!), but my ME student project includes
programming a board (storage of data not required, but would be nice). So I've modified
some code, and learned a bit about bits and hex.

In order to make sure it would fit, I determined the size of my array:

"pseudocode:"

struct {
unsignedint year;
unsignedint counts;
unsignedint electric_cost;
} Array[13][32];

1 - year, max # 99 -> 1 byte
2 - counts, max # 999999999 -> 4 bytes
3 - electric cost, max # 99999 -> 3 bytes

So, to calculate data size, ([0] is not mapped, can but would add several calculations as I'm
using current year and day to point to the array):

12 * 31 * 8 bytes = 2,976 bytes

So, in essence I'm creating one heckuva large array (too big for this chip?), and would like
to store it's values in EEPROM every 15 minutes or so. When the chip starts up, I'd like it to
initialize the array with the values stored in EEPROM, etc... To be brutally honest, the array
is not going to be fully used (only this month forward), but I'd like it to be as realistic as
possible.

I do not understand assembly, and already have the main program in c. I've been searching
for examples, but none can be found. Is this too ambitious? I'm not too worried about
writing too much (this is for a project, so it won't run full time) to the EEPROM. Looking
over the archives, FRAM sounds like it'd work, but I do not have the time to add another
chip to the board (unless it'd be straightforward).

Thanks!

John Pariseau




OK, so I asked a bit too soon. I checked the files and there are some h and c files for
implementing eeprom reading/writing.

I still am not too sure what to do with it, though, as the instructions for the board are:

-------

Do not apply EEprom addesses FE0 > FFF. These are reserved for the monitor autostart
and future monitor upgrades.

-------

I obviously do not want to ruin my board! I've never had to address memory directly
before, so this is not all that clear to me what to do.

Thanks!




Also,

are there any good guides to memory addressing on the net, for beginners?



Are you simply having trouble understanding the memory layout? Any array declared as you have it will be stored in one contiguous chunk of memory, and the first element
will be the first byte at the first address. You don't need assembly for this.

To take advantage of the smaller sizes of values, you may want to re-declare your structure:

struct fileRecord{
unsigned char year;
unsigned int counts;
unsigned int electric_cost;
} fileRecord;

Then create a pointer to the structure, this will later be populated with the first address

struct fileRecord Array[13][32];
struct void *pFirstElement;

pFirstElement = (void *)&Array[0][0]; //Get the first address of the element.

memcpyEEPROM(&destAddress, pFirstElement, sizeof(Array)); //Copies entire array to the EEPROM at it's destAddress location.

I just separated out your declaration for Array so that the definition of the structure can be re-used, and it allows some more flexibility using size().

***************
However if you are trying to save data over time periodically to the EEPROM, you may be better off saving only a single element at a time, rather than the whole array. I call it journaling. So instead:

struct fileRecord element; //Only a single element to deal with

element.year = 04; //Represents filling the element.
element.counts = 455;
element.electric_cost = 45;

memcpyEEPROM(&destAddress, (void *)&element, sizeof(fileRecord)); //Copies only a single element in the array.
destAddress += sizeof(fileRecord); //Increment destination address for the next piece of data.

This has several advantages: It requires less RAM, it lessens the amount of data loss if the power goes out, It provides load balancing (meaning you are not erasing and writing the same memory locations over and over), and it is easier to work with.

When you first power up the unit and there is already data stored in the EEPROM, you can derive the next available free location by looking for the first 0xFF that .year returns when you read through the EEPROM one element at a time.

----- Original Message -----
From: Simplymail
To: 68HC12@68HC...
Sent: Saturday, March 26, 2005 12:44 PM
Subject: [68HC12] Help needed storing array in EEPROM
I'm using this board:

http://www.axman.com/education/edc_hc12.html

a DS1305, hall sensor, LCD, Keypad.

Compiled with GNU for 68HC11 & 68HC12
EmbeddedGNU

The data collected from the hall is time stamped, and
two different arrays are created - one with 23 rows (for every hour of the day, military
time), and one for an entire year. The board works, outputs the two arrays to the serial
port. Yea.

I'd like to now store just the yearly array to EEPROM, and read it on startup (with the option
of erasing the memory). Is this easily possible? The code is in C, not assembly. Would it be
easier to just make a backup power supply?

Anyhow, I read both tech notes (AN2400/D, AN2302/D), and somewhat understand what
they are saying. I'm not an EE (but trying!!), but my ME student project includes
programming a board (storage of data not required, but would be nice). So I've modified
some code, and learned a bit about bits and hex.

In order to make sure it would fit, I determined the size of my array:

"pseudocode:"

struct {
unsignedint year;
unsignedint counts;
unsignedint electric_cost;
} Array[13][32];

1 - year, max # 99 -> 1 byte
2 - counts, max # 999999999 -> 4 bytes
3 - electric cost, max # 99999 -> 3 bytes

So, to calculate data size, ([0] is not mapped, can but would add several calculations as I'm
using current year and day to point to the array):

12 * 31 * 8 bytes = 2,976 bytes

So, in essence I'm creating one heckuva large array (too big for this chip?), and would like
to store it's values in EEPROM every 15 minutes or so. When the chip starts up, I'd like it to
initialize the array with the values stored in EEPROM, etc... To be brutally honest, the array
is not going to be fully used (only this month forward), but I'd like it to be as realistic as
possible.

I do not understand assembly, and already have the main program in c. I've been searching
for examples, but none can be found. Is this too ambitious? I'm not too worried about
writing too much (this is for a project, so it won't run full time) to the EEPROM. Looking
over the archives, FRAM sounds like it'd work, but I do not have the time to add another
chip to the board (unless it'd be straightforward).

Thanks!

John Pariseau

------
Yahoo! Groups Links

a.. To


Hi,

You'll do everything below as suggested by Mark W and then wonder why it
doesn't work. Or some of it will appear to work and then suddenly won't.

Here's the problem. It's pretty easy to define a pointer to an array of
data and set that pointer to the memory mapped EEROM. Trivial in fact. And
getting data from the EEROM is also trivial for the most part.

eeromPtr = (char *)0xF000; // for example.

var = eeromPtr[4]; // Get the byte.

But now think of the technology you are dealing with. Check out the data
sheet for writing to the EEROM. Oops! There's a short interval after
writing where the EEROM is busy internally solidifying the data and a second
write will be ignored -- that's true for all EEROM technologies. A bit of
further investigation and you'll find that in fact you first need to set up
a sequence to even write to a given location. That's useful because an
errant pointer and a programming error could write over your EEROM so this
is a good thing.

That means to write to the EEROM you can't just memcpy or eeromPtr[4] =
0x23;

You need to write a function that takes an address and data and writes it to
the EEROM. Since the (9S12) EEROM is set up as 32 bit pages, you need to
read all 4 bytes, figure out within the 4 where yours goes and then write
back all 4 bytes. If you are writing a 16 bit variable, what happens if
the two bytes overlap a 32 bit page boundary.

Don't ask me how I know all this because I'll just tell a fib..... 8-)

John Dammeyer

Wireless CAN with the CANRF module now available.
http://www.autoartisans.com/products
Automation Artisans Inc.
Ph. 1 250 544 4950 > -----Original Message-----
> From: Mark W [mailto:mark@mark...]
> Sent: Saturday, March 26, 2005 12:10 PM
> To: 68HC12@68HC...
> Subject: Re: [68HC12] Help needed storing array in EEPROM >
> Are you simply having trouble understanding the memory
> layout? Any array declared as you have it will be stored in
> one contiguous chunk of memory, and the first element
> will be the first byte at the first address. You don't need
> assembly for this.
>
> To take advantage of the smaller sizes of values, you may
> want to re-declare your structure:
>
> struct fileRecord{
> unsigned char year;
> unsigned int counts;
> unsigned int electric_cost;
> } fileRecord;
>
> Then create a pointer to the structure, this will later be
> populated with the first address
>
> struct fileRecord Array[13][32];
> struct void *pFirstElement;
>
> pFirstElement = (void *)&Array[0][0]; //Get the first
> address of the element.
>
> memcpyEEPROM(&destAddress, pFirstElement, sizeof(Array));
> //Copies entire array to the EEPROM at it's destAddress location.
>
> I just separated out your declaration for Array so that the
> definition of the structure can be re-used, and it allows
> some more flexibility using size().
>
> ***************
> However if you are trying to save data over time periodically
> to the EEPROM, you may be better off saving only a single
> element at a time, rather than the whole array. I call it
> journaling. So instead:
>
> struct fileRecord element; //Only a single element to deal with
>
> element.year = 04; //Represents filling the element.
> element.counts = 455;
> element.electric_cost = 45;
>
> memcpyEEPROM(&destAddress, (void *)&element,
> sizeof(fileRecord)); //Copies only a single element in the array.
> destAddress += sizeof(fileRecord); //Increment destination
> address for the next piece of data.
>
> This has several advantages: It requires less RAM, it lessens
> the amount of data loss if the power goes out, It provides
> load balancing (meaning you are not erasing and writing the
> same memory locations over and over), and it is easier to work with.
>
> When you first power up the unit and there is already data
> stored in the EEPROM, you can derive the next available free
> location by looking for the first 0xFF that .year returns
> when you read through the EEPROM one element at a time.
>
> ----- Original Message -----
> From: Simplymail
> To: 68HC12@68HC...
> Sent: Saturday, March 26, 2005 12:44 PM
> Subject: [68HC12] Help needed storing array in EEPROM >
> I'm using this board:
>
> http://www.axman.com/education/edc_hc12.html
>
> a DS1305, hall sensor, LCD, Keypad.
>
> Compiled with GNU for 68HC11 & 68HC12
> EmbeddedGNU
>
> The data collected from the hall is time stamped, and
> two different arrays are created - one with 23 rows (for
> every hour of the day, military
> time), and one for an entire year. The board works, outputs
> the two arrays to the serial
> port. Yea.
>
> I'd like to now store just the yearly array to EEPROM, and
> read it on startup (with the option
> of erasing the memory). Is this easily possible? The code
> is in C, not assembly. Would it be
> easier to just make a backup power supply?
>
> Anyhow, I read both tech notes (AN2400/D, AN2302/D), and
> somewhat understand what
> they are saying. I'm not an EE (but trying!!), but my ME
> student project includes
> programming a board (storage of data not required, but
> would be nice). So I've modified
> some code, and learned a bit about bits and hex.
>
> In order to make sure it would fit, I determined the size
> of my array:
>
> "pseudocode:"
>
> struct {
> unsignedint year;
> unsignedint counts;
> unsignedint electric_cost;
> } Array[13][32];
>
> 1 - year, max # 99 -> 1 byte
> 2 - counts, max # 999999999 -> 4 bytes
> 3 - electric cost, max # 99999 -> 3 bytes
>
> So, to calculate data size, ([0] is not mapped, can but
> would add several calculations as I'm
> using current year and day to point to the array):
>
> 12 * 31 * 8 bytes = 2,976 bytes
>
> So, in essence I'm creating one heckuva large array (too
> big for this chip?), and would like
> to store it's values in EEPROM every 15 minutes or so. When
> the chip starts up, I'd like it to
> initialize the array with the values stored in EEPROM,
> etc... To be brutally honest, the array
> is not going to be fully used (only this month forward),
> but I'd like it to be as realistic as
> possible.
>
> I do not understand assembly, and already have the main
> program in c. I've been searching
> for examples, but none can be found. Is this too ambitious?
> I'm not too worried about
> writing too much (this is for a project, so it won't run
> full time) to the EEPROM. Looking
> over the archives, FRAM sounds like it'd work, but I do not
> have the time to add another
> chip to the board (unless it'd be straightforward).
>
> Thanks!
>
> John Pariseau >
>
> --------------------------
> ----------------
> Yahoo! Groups Links
>
> a.. To > Yahoo! Groups Links >





Combining both your responses, I'm going to reply...

Basically, I never considered different approaches to storing data, beyond putting it into
EEPROM. Thank you for that reasoning.

The *problem* I have is this:

If data for 12 (Dec), 25 is stored in a certain location in EEPROM, how do I know where that
location is when I go to read the data? Do I have to loop through the EEPROM? Do I have to
store the 12 and the 25 values?

Originally, my plan for storing the struct array was just one month, so it was of size [31].
However, I realized if I used the array as such: [12][31] then I could just reference the date
above as array[12][25] (my previous email may have had this wrong) and capture the entire
year. Once this worked out, I wanted to store the array for permanent storage.

Here is the problem: Can I statically determine where each value will be put? If so, what
happens if a memory location goes bad on the EEPROM? Or is that unlikely?

And, if it is unlikely the data will go bad, I have a starting point with both of your
responses, but am lacking some info still...



Hi,

The answer is yes, you can determine statically where you put the data.
However, writing out an entire year's worth of data each time is rather
inefficient. OTOH, writing out 25DECXX data once per second isn't the best
idea either.

Your algorithm that needs to store the data will decide how often you update
and you'll program that frequency based on EEROM life projected from the
data sheet.

It all depends on how much EEROM you have and how much data you want to
store and how often. All of those are project dependant values.

For example, if you are worried about EEROM cell failure then you could use
an index table to point to the data. Kind of like formating a directory on
a floppy drive disk. Create 366 pointer entries (16bit) that point to each
days record data. The data part is formed as an array of 500 records. Now
fill in the index table with the first 366 indexes to the records. (I'm
assuming fixed record size here).

Next calculate what day of the year 25DecXX is and index to that record. IF
the data in that record is corrupted because of EEROM failure change the
index value to point to a new free record from the list of 500. Since you
only write to the index table if an EEROM record fails, you won't exceed
the write cycles for that.

And, with a little bit of work you can test the entire algorithm on a PC.
Create a file the size of your EEROM with record sizes the size of your data
record. Initialize it to 500 empty records. Create a second file that is
your index table. Fill the first 366 locations with the #'s 1 to 365.

Now create the functions that will write out the data to the correct file
location based on the date. With minor tweaking and adding code to
read/write the EEROM instead of the disk drive, you'll have tested code that
works.

There are hundreds of solutions to your 'problem' Some are elequent and
others are clumsy or unreadable except to the original author.

All part of the fun.

John Dammeyer

>
> Basically, I never considered different approaches to storing
> data, beyond putting it into
> EEPROM. Thank you for that reasoning.
>
> The *problem* I have is this:
>
> If data for 12 (Dec), 25 is stored in a certain location in
> EEPROM, how do I know where that
> location is when I go to read the data? Do I have to loop
> through the EEPROM? Do I have to
> store the 12 and the 25 values?
>
> Originally, my plan for storing the struct array was just one
> month, so it was of size [31].
> However, I realized if I used the array as such: [12][31]
> then I could just reference the date
> above as array[12][25] (my previous email may have had this
> wrong) and capture the entire
> year. Once this worked out, I wanted to store the array for
> permanent storage.
>
> Here is the problem: Can I statically determine where each
> value will be put? If so, what
> happens if a memory location goes bad on the EEPROM? Or is
> that unlikely?
>
> And, if it is unlikely the data will go bad, I have a
> starting point with both of your
> responses, but am lacking some info still...
>




>Don't ask me how I know all this because I'll just tell a fib..... 8-)

I won't look in the mouth. Good advice though. I need to start DP256
eeprom for the first time and I see that I will need to beef up my low
level driver.

The crude eeprom filesystem that I use is to is "label" your data
(collected into a "file" and given a name) and wrapped by a header with
size info that allows one to step along until a header with the right
"label" or filename match is made. The header can even contain a bitfield
that indicates active/erased status to somewhat improve an inefficient
scheme.

Wear leveling is effected by writing until the eeprom space is consumed
and then doing a defrag. Not code that you knock off in a day from
scratch and maybe not practical for some apps.

The real down and dirty method is to simply hardcode certain addresses for
specific variables with the smallest granularity possible (32 bit data).

Rob Milne



Just to add to the previous.

The Pb of dysfunctional eeprom cells can only be solved by reading back
all of your writes (including the delete bitfield write for the crude
filesys).
Re-adjusting the linking pointers to bypass bad locations can be tricky if
the pointers themselves are faulty. Don't get too obsessed with faulty
memory if you aren't near the limits. Otherwise obsess with integrity
checks and redundancy schemes.

Rob Milne



I wanted to add one more thing in light of what others are suggesting:

Declare your structure as follows:
struct fileRecord{
unsigned char year;
unsigned int counts;
unsigned int electric_cost;

unsigned char crc;
} fileRecord;
And that will allow you to save the cyclic redundancy check value as the
last value written to the EEPROM during a record update. To calculate the
CRC, simply access your record as bytes:
sruct fileRecord myRecord;

unsigned char *pCharMyRecord;

short I;
myRecord.crc = 0;

pCharMyRecord = (unsigned char *)&myRecord;

for(I = 0; I < sizeof(fileRecord) - 1; I++) //Don't include the
CRC byte in the calculation

{

myRecord.crc += pCharMyRecord[i];

}
myRecord.crc = !myRecord.crc; //Invert data (prevents the case of all
zeros failure).

//Now write the data.
Perform the same calculation when you have read the data from the EEPROM and
see if the CRC read is the same as that calculated.
Now when you read data from the EEPROM, you can tell when the write went bad
by looking at the CRC vs. data the record contains. This will find a vast
majority of errors, but could potentially fail in the case of if the CRC
happens to match the erroneous data. This is a good start however, and is
more than enough if in a non-critical application. You can increase
reliability by increasing the CRC data size holder to two bytes so that the
value doesn't overflow, but in the interest of saving space, you can
truncate it to a single byte.
Another word of caution: Depending on what compiler you are using and what
options, it may force padding on elements in your structure. For example a
16-bit processor and compiler may allocate two bytes for "unsigned char
year" rather than just one byte to keep the data on even word boundaries.
The same may be true for CRC. You can easily check for this by sprintf() the
sizeof() the structure and see if agrees with what you calculate. If it
doesn't match, you will have to do things at the least common denominator of
size, say a word rather than a byte, or try a few other options.
-Mark Wyman
_____

From: robmilne@robm... [mailto:robmilne@robm...]
Sent: Saturday, March 26, 2005 9:54 PM
To: 68HC12@68HC...
Subject: RE: [68HC12] Re: Help needed storing array in EEPROM
Just to add to the previous.

The Pb of dysfunctional eeprom cells can only be solved by reading back
all of your writes (including the delete bitfield write for the crude
filesys).
Re-adjusting the linking pointers to bypass bad locations can be tricky if
the pointers themselves are faulty. Don't get too obsessed with faulty
memory if you aren't near the limits. Otherwise obsess with integrity
checks and redundancy schemes.

Rob Milne

<http://us.ard.yahoo.com/SIG98i4b5p/M)8184.6191685.7192823.3001176/D=gr
oups/S06554205:HM/EXP11978451/A%93423/R=0/SIGel9gslf/*http:/www.n
etflix.com/Default?mqso`190075> click here
<http://us.adserver.yahoo.com/l?M)8184.6191685.7192823.3001176/D=groups/S=
:HM/A%93423/rand8892665
_____

> Terms of Service.



The 2024 Embedded Online Conference