read/write EEPROM on 18F8520

Anybody that knows how to do it want to summarize how to read and write the EEPROM on the 18F8520?

There are some functions in the C18 libraries for EE access, but looks like they use I2C and I don’t thinks that’s needed for the on-chip EEPROM. The compiler also has provision for declaring variables in EEPROM (the rom storage qualifier) and says it generates the TBLWT instruction to write to it, but warns that there may be more code than that requires. Indeed, the 18F8520 data sheet gives all the details, using special regs EECON1, EECON1, TABLAT and TBLPTR. So do we drop into assembly to use EEPROM or is there some library support for it? Anybody want to provide the functions?

EDIT: it’s actually EECON1, EECON2, EEDATA, EEADRH, EEADR that are used for EEPROM access. The regs noted above are for accessing program flash memory.

Also - the data sheet says we have 1024 bytes of EEPROM. Why does IFI say we only have 255 bytes? Is the rest of it reserved for their use or is it a typo or what?

Thanks for any help.

Bill Bennett

[Edit] As to why they claim you only have 255 bytes? I don’t know. There appears to be nothing in there at all. And I can write to bytes >0xFF so not really sure
[/edit]

This should suit you needs:



unsigned char readEE(unsigned char addrH,unsigned char addrL)  {
  	EEADRH = addrH;
 	EEADR =addrL;

    	  
  	EECON1bits.EEPGD =0;
  	EECON1bits.CFGS =0;
  	EECON1bits.RD =1;


    	return EEDATA;
}

void writeEE(unsigned char addrH,unsigned char addrL,unsigned char data)
{
  	EEADRH = addrH;
  	EEADR =addrL;
  	EEDATA = data;

  	  	//following as per spec. sheet
  	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;
}


Thanks for the code.

I suppose the reason you don’t have to block interrupts throughout both functions is that interrupt state save process saves and restores the registers, but you have to make sure the write process itself is not interrupted, which could corrupt the slow write if the address or data was changed before it completed.

Thanks again.

Couple of questions…

  1. Can you explain addrH, addrL, and data a little more? For readEE, are these the locations of the high and low byte in the EEPROM where you want to write? What are typical values for these addresses, if so? For writeEE same thing?

  2. I read in another thread that you (or someone) is developing a copyCat (?) where you’d record user input into the EEPROM. How big (bytes) is the EEPROM? Do you have sample code for the CopyCat?

I’m new to the forum…so I hope I’m asking the right questions in the right place.

Thanks!

Here is a slightly improved version of the read/write function. I’ve combined addrH and addrL into address. Valid values for address should be 0-1024 (since the size of the EEPROM is 1KB). (IFI originally said that it was only 256 but they have since corrected their mistake)

data can be any char value (0:255 for unsigned; -128:127 for signed)

This is applicable to both readEE() and writeEE()

 
char readEE(unsigned short address) {

// Load address into address register
EEADRH = ((address>>8)&0x03);   //Bits 2-7 are masked off since EEPROM is only 1KB
EEADR =(address&0xFF);

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


return EEDATA;
}

void writeEE(unsigned short address, char data)
{
EEADRH = ((address>>8)&0x03);
EEADR =(address&0xFF);
EEDATA = data;

//Configuration 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;
}

EEPROM size is 1024 bytes (1KB)

I am not the person working on the CopyCat program. Post in this thread for any questions on CopyCat.

Welcome! And, yes you are in the right location.

I am still learning and acquainting myself with all these crazy ideas about EEPROM and ROM and RAM and memory locations and all that stuff. I know how to program in C and have written some code for the eduBOts but its nothing too advanced. I want to load a table/list of sin values (0:90 degrees, to maybe 3 or 4 place accuracy) into ROM so that I can access it from my main program loop. When and how do I read it in? I understand that you use the above read and write functions but WHERE and WHEN do you use them?

Although you might want to finish understanding how to manage the ram, program memory, and eeprom, eeprom is probably not the best choice for your sine table. The C compiler allows putting read-only data in program memory. The loader will automatically put your table in program rom, and the compiler will automatically generate the appropriate code to access it there. This would be the easiest way to do your sin table. You wouldn’t have to read it in or anything special. Just declare it to be in rom, like this:

unsigned char /* or whatever you want */ rom sinTable[256] = {0, 5, 10, 15, … more table values…};

The rom keyword will cause this table to be stored in rom rather than ram, the latter being the much more limited resource. Declared this way, you can access it in C just like any other array. Just don’t try to store to it.

Now, if you really want to put it in EEPROM, the simplest way would be to declare the table as above, run a for loop to copy the table to EEPROM using writeEE provided by Random Dude in the prior post. Download the program and run it, just once, and the EEPROM will be saved until changed by some other program. After that download a program that accesses the table using readEE.

A more typical use for the EEPROM would be, for example, calibration of a resistive sensor. If for some reason the sensor calibration changes often, you could have code that is always loaded that can run a calibration sequence and store the resulting data in EEPROM, and the normal runtime could access the current calibration from that table.

Have fun.

Bill

AH-HA. I had misunderstood what the EEPROM was. As I understand it now it is 1KB of space where you put code that is run every time the bot is powered on?? No. That doesn’t seem quite right. I’m not sure. I guess I thought that EEPROM was just the ROM, but its something different. Is there any threads out there or webpages that I can read that deal with RAM ROM EEPROM and memory storage to clarify my young mind?
thanks. you rock.
Bill

You can’t put code in the EEPROM, there’s no provision for executing it there. It’s 1K of space where you can put “stuff” that you want to be there even after the power is turned off and back on. In that sense, it’s not very different than program rom. The main distinction is that it’s a little harder to read than data stored in program memory, but easier for your program to write.

To elaborate a bit on the sensor calibration, as an example of what the EEPROM is good for: We are building a prototype that has steering sensors on the wheels. The mechanical alignment of the sensors is hard to predict accurately, and likewise the proportional relationship between the sensor readout and the angular position is hard to know in advance. So we have a calibration routine that can be run at any time by a switch at the OI. During this calibration routine, the operator can put the wheels at several specific positions and “click” the joystick trigger to store the sensor reading at those positions in EEPROM. These readings are later used to interpolate the angle to a reasonable accuracy during regular operation of the 'bot.

A reasonable rule of thumb for the ram, program rom, and eeprom is:

  • program rom for code, and for data known at compile time
  • ram for read/write variables at run time
  • eeprom for data that is determined at run time and needs to be stored permanently so it is known at next run of the 'bot

Hope this helps clarify.

Bill

Those last three lines made it soooo clear. Thanks so much for your help and assistance. One last question. If I read something into ROM will it still be there the next time I turn on the bot?

Program rom and EEPROM are both non-volatile memory - they will be there, even through a power off/on sequence, until re-written with new data. Variables in ram go away of course.

Bill

Alrighty. With any luck this will be my final question. We have 1800 bytes of variable space. Is there any set space for RAM and ROM? Or can you declare any amount of RAM and ROM as long as it isn’t more that 1800 bytes?

Program rom is 32k. This is all the all the program you write, plus any data you declare as rom, plus any library code you link in (in the default code, this is clib.lib and 18f8520user.lib). The default framework takes about 8k, so if you don’t change that, you’ve got about 24k for your program and rom data.

The program rom usage can be examined in the .map file produced after you do a build. It’s not real nice to read, but look for the lines after “program memory usage” for a simple summary of how much you’re using.

Your non-rom variables go in the 1800 bytes of ram. I don’t see any nice summary of total usage for this, but look at the lines for “DATA”. I also haven’t figured out why the number is 1800, the chip has 2048 bytes. Maybe what they’re saying is library code needs 200 bytes, and there’s 1800 bytes left. Not sure.

The EEPROM is 1024 bytes, and usage won’t show up in the link map, since the addresses are all generated at run time. The linker doesn’t know anything about this. Your program has to determined what is stored at 0, what at 1, and so on.

Bill

A little more info about writing the EEPROM - it takes time. To write one byte takes about 4 ms. Since the loop time is 26 ms (or 17 on the EDU-RC), if you try to write a few bytes at once, you use up more than all of the time. Even worse, if you don’t wait for the write to finish, only the first write will work.

I am working on some code to keep a small queue of bytes to write that will wait for each to write before writing the next. Will post when I think it’s working. Anybody else have thoughts on how best to manage this issue?

Bill

Section 7.2 of the data sheet mentions an EEwrite complete interrupt.

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

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

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.

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 :smiley:

Have fun

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