Chief Delphi

Chief Delphi (http://www.chiefdelphi.com/forums/index.php)
-   Programming (http://www.chiefdelphi.com/forums/forumdisplay.php?f=51)
-   -   read/write EEPROM on 18F8520 (http://www.chiefdelphi.com/forums/showthread.php?t=22655)

WizardOfAz 12-01-2004 15:00

Re: read/write EEPROM on 18F8520
 
I don't yet have EEPROM read and write working reliably. It works erratically, and I've not yet figured out what I'm doing wrong. I found this couple of paragraphs in the 18Fxx20 data sheet, which I can't make sense of. I doubt it's related to my problem, but would anyone like to try to interpret it?

This is it:
7.8 Using the Data EEPROM
The data EEPROM is a high endurance, byte addressable
array that has been optimized for the storage of
frequently changing information (e.g., program variables
or other data that are updated often). Frequently
changing values will typically be updated more often
than specification D124. If this is not the case, an array
refresh must be performed. For this reason, variables
that change infrequently (such as constants, IDs, calibration,
etc.) should be stored in FLASH program
memory.

A simple data EEPROM refresh routine is shown in
Example 7-3.

Note: If data EEPROM is only used to store constants
and/or data that changes rarely, an
array refresh is likely not required. See
specification D124.

(specification D124 is missing from the 18Fxx20 data sheet, but is included in the errata)

Param=D124 Sym=TREF Characteristic=Number of Total Erase/Write Cycles before Refresh(4)
min=1M typ=10M (no max) unit=E/W Conditions -40°C to +85°C

BananaMango777 12-01-2004 15:19

Re: read/write EEPROM on 18F8520
 
Typically what you do is have a buffer (a location in conventional flash memory) which stores data in a que structure to be written to the eeprom. Then you write a procedure for the "on finish eeprom write" interrupt to check whether there is anything in the que and then write it if there is. By using interrupts you do not waste processing time using loops etc for things to be written to the eeprom as you can execute a lot of code in a few ms.
Am I right in assuming you are writing the majority of you're code using the c compiler? Our team will be writing in assembler as most of us have experience using the pic microcontrollers for various projects etc. I can write some working code in assembler which will do what I have described above and get it on the forum asap.

The pic datasheets really are very useful, I would advise that you read the eeprom section which explains about the special registers associated with writing to the internal eeprom and the interrupts available.

Hope this helps.. and good luck

WizardOfAz 12-01-2004 15:33

Re: read/write EEPROM on 18F8520
 
Hi, thanks. I did read the data sheet about EEPROM, and mostly understand it, but the section I pasted from the data sheet in my previous post was pretty confusing. I'm looking for someone else's interpretation.

Also, I am working on a queued method of writing the EEPROM and have it mostly working. So unless you really want to, no need to write one for me. I will post mine when I think it's done and working.

BananaMango777 12-01-2004 18:23

Re: read/write EEPROM on 18F8520
 
to be honest... unless you want to store data for analysis later, its far easier just to use the flash memory as its far quicker and easier to use within the code quickly. As it is the control board has a backup battery which keeps the pic powered all the time, in sleep mode whic requires somethink like <10uA If I remember correctly. Although I supose It depends on what you are doing, best of luck anyway, I hadn't intended writing the code yet so I wont bother writing the library file if you are already in the process. Don't hesitate to post questions etc as I'm a bit of a Hex basher and like doing this kind of thing for fun in my spare time and can normally shed some light on most problems :D

Have fun

BananaMango777 12-01-2004 18:37

Re: read/write EEPROM on 18F8520
 
basically what that extract says in plain english:

- you can store data in byte addressable locations.. i,e. a memory address FF
- it is non volatile and you can have many reads/writes using eeproms - typically they have a lifetime of around 10,000 writes/flashes
- for data that does not change indefinately such as constants, flash memory should be used, or you can refresh the eeprom to varify the data integrity... (this really doesnt apply for first :D... data in eeprom is good for a few years or so, depending on the technology).. Refreshing eeprom basically puts a voltage accross the array such that all the data is completely erased and then rewritten to verify the integrity of the data. This should be done every X writes (stated in the datasheet) to remove stray charges that may build up after multiple writes, which could corrupt the data written.

The figures at the bottom state the environment for which the time stated in D124... (which is a microchip app note common for pics using the same eeprom technology) is true for... i.e. at this temp, humidity etc you need t refresh you'r e eeprom every Xmonths/years/whatever (this will be a long time... way way beyond the actual event if you were to program the pic now for a single write ;)... or how many writes you have before you need to refresh to be safe)


For more info look up "refreshing" and RAM... computers do this all the time to keep your ram in your computer happy as its volatile, i.e. the data is only good for so long before you need to refresh it otherwise you lose the data...
Hope this is useful

WizardOfAz 13-01-2004 02:14

Re: read/write EEPROM on 18F8520
 
What we're using the EEPROM for is to store calibration data for steering sensors. If we do any adjustment on the wheel mechanism, the alignment of the wheel to the sensor can change, and I want a way to collect and save away the sensor angle offset from the wheel angle without requiring a programmer's help to modify the constants in the code and recompile/reload it.

I've got this code working now as far as I can tell. Here it is for anybody interested. I'm wide open to feedback if anybody finds a problem with it or wants to suggest an improvement.

readEE returns the result immediately, since there is no required delay for reading. But you can't change the ee address register while a write is in progress, so readEE returns 0 if a write is in progress. This doesn't help of course, you really need to just make sure you don't do this.

writeEE puts the byte to be written on a 16 byte queue in ram, then calls processEEQueue which starts the EE write sequence. If you then call writeEE more times without some delay, the byes get added to the queue but processEEQueue does not write them since the first one is not finished writing. You have to call processEEQueue again later, multiple times with some delay between to get them all written. It doesn't hurt to call processEEQueue too much, it returns quickly if the queue is empty. What I did it call processEEQueue every time around in the main loop.

(sorry for the lack of indentation - the cut/paste into the forum threw them away)

file eeprom.h
------------
#ifndef _eeprom_h
#define _eeprom_h
#include "ifi_picdefs.h"
unsigned char readEE(unsigned short address);
void writeEE(unsigned short address, unsigned char data);
void processEEQueue(void);
#endif

file eeprom.c
------------
#include <string.h>
#include "eeprom.h"

/************************************************** ******************************/
/* read and write eeprom */
/* basic code donated by "random dude" and obtained from chiefdelphi forums */
/* queing mechanism added by bill */
/************************************************** ******************************/
typedef struct {
unsigned writeInProgress:1;
unsigned bufferNotEmpty:1;
unsigned bufferFull:1;
unsigned :4;
unsigned bufferPtr:4;
unsigned bufferEnd:4;
unsigned char dataBuffer[16];
unsigned short addressBuffer[16];
} eeControlStruct;
static eeControlStruct eeControl = {0,0,0,0,0,0,}; // initialize control bits and pointers to false

unsigned char readEE(unsigned short address) {

// should not change EEADR/EEADRH while a write is happening
if(eeControl.writeInProgress) return 0;

// Load address into address register
EEADRH = (unsigned char)(address>>8);
EEADR = (unsigned char)(address&0xFF);

//Configuration as per manual
EECON1bits.EEPGD =0;
EECON1bits.CFGS =0;
EECON1bits.RD =1;
return EEDATA;
}

void writeEE(unsigned short address, unsigned char data)
{
if(eeControl.bufferFull) return;
eeControl.dataBuffer[eeControl.bufferEnd] = data;
eeControl.addressBuffer[eeControl.bufferEnd++] = address;
eeControl.bufferFull = (eeControl.bufferEnd==eeControl.bufferPtr);
eeControl.bufferNotEmpty = 1;
processEEQueue();
}

// call this once each main loop, or more often, to process the queue
// of bytes to be written to eeprom. Note that there is no buffer
// overrun detection. Enlarge the buffer and change the size of bufferPtr
// and bufferEnd if you need more buffer space to avoid overrun.
void processEEQueue(void) {

if(eeControl.writeInProgress && !PIR2bits.EEIF) return; // previous write not complete
PIR2bits.EEIF = 0; // reset EE write done interrupt flag
if(!eeControl.bufferNotEmpty) {
eeControl.writeInProgress = 0;
return;
}

// OK, previous write is done and something is in the buffer, write it
eeControl.writeInProgress = 1;

// Load address into address register
EEADR = (unsigned char)(eeControl.addressBuffer[eeControl.bufferPtr]&0xff);
EEADRH = (unsigned char)(eeControl.addressBuffer[eeControl.bufferPtr]>>8);
EEDATA = eeControl.dataBuffer[eeControl.bufferPtr++];
eeControl.bufferNotEmpty = (eeControl.bufferPtr != eeControl.bufferEnd);

// with a little more work, we could check for error on previous write and redo it

// write sequence as per manual
EECON1bits.EEPGD =0;
EECON1bits.CFGS =0;
EECON1bits.WREN =1;
INTCONbits.GIE = 0;
EECON2 = 0x55;
EECON2 = 0xAA;
EECON1bits.WR = 1;
INTCONbits.GIE = 1;
EECON1bits.WREN = 0;
}

Paul 20-01-2004 16:55

Re: read/write EEPROM on 18F8520
 
:confused: I was going over the code given on this post and I was wondering what memory address's are avalible to write to? And how much information can be fit into a single address when using unsigned chars? Any help would be appreciated.

Mike Betts 20-01-2004 17:41

Re: read/write EEPROM on 18F8520
 
Quote:

Originally Posted by Paul
:confused: I was going over the code given on this post and I was wondering what memory address's are avalible to write to? And how much information can be fit into a single address when using unsigned chars? Any help would be appreciated.

I have not looked at the Wizard's code, but traditionally, one byte (8 bit or (un)signed char) is one address location. Words, AKA 16 bit values such as integers) will take up two adjacent addresses. Most processors will require words to be aligned on even address boundries.

Astronouth7303 20-01-2004 17:48

Re: read/write EEPROM on 18F8520
 
A few questions:
a. What's EEADRH, EEADR, EEDATA, EECON2, and the rest of it? :confused:
b. what's the >> in "EEADRH = ((address>>8)&0x03);"? :confused: :o

And yes, I should probably know already.

Random Dude 20-01-2004 18:21

Re: read/write EEPROM on 18F8520
 
Quote:

Originally Posted by Astronouth7303
A few questions:
a. What's EEADRH, EEADR, EEDATA, EECON2, and the rest of it? :confused:
b. what's the >> in "EEADRH = ((address>>8)&0x03);"? :confused: :o

And yes, I should probably know already.


a: those are registers in the micro. See the doc linked someplace earlier in this thread for a little more detail.

b: (address>>8) bit shifts 'address' 8 bits to the right ( the << operator does shifts to the left )

WizardOfAz 21-01-2004 00:30

Re: read/write EEPROM on 18F8520
 
Quote:

Originally Posted by Paul
:confused: I was going over the code given on this post and I was wondering what memory address's are avalible to write to? And how much information can be fit into a single address when using unsigned chars? Any help would be appreciated.

Addresses 0 through 1023 are available in EEPROM. Each stores one byte, which is a char or unsigned char, whatever you like. 8 bits. If the data you're trying to store is already 8 bits like you say, it's pretty easy. Just do
writeEE(someAddress, someChar);

If you want to store a value that is more than 8 bits, like a 16 bit short or int, or a 32 bit long, you have to break it up into bytes first. And be careful with sign management. The cleanest way, I think, to store both bytes of an int would be like this:
int i;
...
writeEE(someAddress, (unsigned char)(((unsigned int)i)>>8)); // write high byte
writeEE(someAddress+1, (unsigned char)(((unsigned int)i)&0xff)); // write low byte

To get that int back out of EEPROM later, use this sequence:
i = (int)(((unsigned short)readEE(someAddress)<<8)
+ readEE(someAddress+1));

But also read what I said about delays in writing. If you want to use my code above and have more than 16 bytes to write, you'll have to either make the buffer bigger or figure out some other way to time it.

Did that help or add confusion?

Bill

WizardOfAz 21-01-2004 00:36

Re: read/write EEPROM on 18F8520
 
Quote:

Originally Posted by Astronouth7303
A few questions:
a. What's EEADRH, EEADR, EEDATA, EECON2, and the rest of it? :confused:
b. what's the >> in "EEADRH = ((address>>8)&0x03);"? :confused: :o

And yes, I should probably know already.

Those EE names are defined in ifi_picdefs.h.
EEADRH is the high byte of the EEPROM address to be read or written
EEADR is the low byte of the address
EEDATA is the data going in or out of EEPROM
EECON1 and EECON2 are control registers used to do EEPROM operations

>> is shift right, << is shift left
((address>>8)&0x03 says divide address by 256 (that's the shift right 8 part) and zero out all but the lowest two bits (that's the &0x03 part).

Bill

Astronouth7303 21-01-2004 07:33

Re: read/write EEPROM on 18F8520
 
Got it.

WizardOfAz 21-01-2004 09:59

Re: read/write EEPROM on 18F8520
 
I noticed there are (at least) two minor flaws in the code above, neither of which would break it.
(1) string.h is not needed. It's there because I had a memset in the code at one point, then got rid of it and didn't remove the include
(2) in the eeControlStruct structure, the line "unsigned :4;" should be "unsigned :5;". The purpose is to get the 4 bit numbers aligned so that the compiled code to access them will be efficient. Maybe the compiler aligned it anyway, I don't know.

Anyway, the code works w/o these changes, since our system uses it with correct results. But I saw them and wanted to pass along the changes to the thousands of you that are using this by now [;-)

Bill

Paul 21-01-2004 22:06

Re: read/write EEPROM on 18F8520
 
Quote:

Originally Posted by WizardOfAz
Addresses 0 through 1023 are available in EEPROM. Each stores one byte, which is a char or unsigned char, whatever you like. 8 bits. If the data you're trying to store is already 8 bits like you say, it's pretty easy. Just do
writeEE(someAddress, someChar);

If you want to store a value that is more than 8 bits, like a 16 bit short or int, or a 32 bit long, you have to break it up into bytes first. And be careful with sign management. The cleanest way, I think, to store both bytes of an int would be like this:
int i;
...
writeEE(someAddress, (unsigned char)(((unsigned int)i)>>8)); // write high byte
writeEE(someAddress+1, (unsigned char)(((unsigned int)i)&0xff)); // write low byte

To get that int back out of EEPROM later, use this sequence:
i = (int)(((unsigned short)readEE(someAddress)<<8)
+ readEE(someAddress+1));

But also read what I said about delays in writing. If you want to use my code above and have more than 16 bytes to write, you'll have to either make the buffer bigger or figure out some other way to time it.

Did that help or add confusion?

Bill

It did help out, however there is one problem. When I write to the eeprom and try to play back from it using the readEE function it doesn't seem to work. I think my memory addresses are off. Would this be an acceptable way of using the writeEE function?
writeEE(0x00,somechar);
or would i have to write it like this?
write(&0x00,somechar);
Thanks for clearing some of the other stuff for me.


All times are GMT -5. The time now is 21:47.

Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi