PDA

View Full Version : reading and writing eeprom



4x5n
10-22-2011, 03:36 AM
I know there are objects in OBEX but I still have a number of questions regarding reading and writing to eeprom. The first is when loading a program from an eeprom does it start at the beginning (IE address 0) and work it's way down? This is important for a number of reasons. The first and most obvious is that I have a board (Gadget Gangsters USB board and Parallax quickstart) that has 64K or ram and would like to use the half unused for my own use to store operating state and variables. I'm also thinking that since I'm not using nearly all the 32K of eeprom that normally included with a propeller board. I'm thinking of using that as well. I know that in that case the data I store will be overwritten when I reload the program but that's OK.

While I'm asking questions about eeproms and their use can someone explain how to read and write to eeprom in english. :-) I've gone through the code in the exchange and it's not making a lot of sense to me. Just a quick paragraph or two so that I can make sense out of the code in the exchange. Thanks in advance.

Mike Green
10-22-2011, 05:48 AM
When loading a program from EEPROM, the loader starts with location zero and copies to the end of the 32K. If there is more than 32K, nothing is accessed beyond the 1st 32K unless your program explicitly does so.

It's possible to write to the locations in EEPROM used to initialize variables in your program, thus providing a persistent initial value that will indeed be erased if you download a new copy of the program to EEPROM.

There are several loaders in the ObEx that will load from other 32K areas of EEPROM. FemtoBasic will do this for you.

Probably the simplest and most straightforward object to use for reading and writing EEPROM is "Basic_I2C_Driver".

4x5n
10-22-2011, 05:42 PM
Mike,

Thanks for your quick response and help. While a search of the OBEX didn't turn up you "basic_i2c_driver" I managed to find it bundled in another object.

The code is clear and help clear out some of the fuzz. It looks like my problem is that I need to searching with google to find the I2C spec and learn the I2C protocol.

ChrisGadd
10-22-2011, 07:45 PM
The datasheet (http://www.datasheetcatalog.org/datasheet2/7/0yuw0yc3x0278cpz78zge08qi13y.pdf) does a decent job of explaining the signalling.

86225
Here's a program I wrote when learning how the EEPROM works, that reads 500 bytes from the beginning of the EEPROM and sends it to the serial terminal.

Quick explanation: I2C is a two-wire protocol, one clock line and one data line, connected as master and slaves. In idle condition, both lines are high. Transmissions begin with a start bit, which is a down-clock on the data line while the clock is high. Aside form the start and the stop, the data line only changes while the clock is low, and data is sampled when clock is high. After eight data bits are transmitted, the receiving device sends an ACK (data line low) to acknowledge receipt of the data, or a NAK (data line high) to signal that it didn't receive. Ends with a stop bit which is an up-clock on data while clock is already high. That's pretty much all there is to I2C.

For my program, I send a start, send the control byte which is the EEPROM code (1010), chip select bits which allow you to address the chip by soldering A0, A1, and A2 to Vcc or ground, in this case (000), and the read/write bit cleared to indicate a write. Since it's a write, the next two bytes contain an address that I want to access inside the EEPROM. Since I want to read from the beginning I transmit $0000. I then send another start bit, which aborts the write operation but leaves the EEPROM address pointer set to $0000. Send the control byte again, except with the read/write bit set this time. After receiving an acknowledge from the EEPROM, the next 8 clocks each read a bit of data. After the eighth bit, I transmit an acknowledge in order to continue reading. After the 500th byte, send a NAK to stop reading, and send a stop bit.

4x5n
10-23-2011, 01:38 AM
Chris, Thanks for your post and link to your pasm code. I was going through it and noticed that at one point you do:
mov cnt,I2C_bit_delay
add cnt,cnt

I don't get the reason for it. I understand you're writing to the "shadow" register but wonder how you read it back again? Don't reads of "cnt" read the counter?

Mike Green
10-23-2011, 02:07 AM
The read-only registers, like CNT, are only valid in the source field of the instruction. If you use that address in the destination field, you get the shadow register. Since the WRxxxx hub writes use the destination field as their data source, you could write the CNT shadow register to hub RAM directly. The WAITCNT uses the destination field for the system clock time to wait for. That works very nicely with the two instructions you've given.

Bits
10-23-2011, 04:38 PM
Try this, the only thing I have left out is the i2c object.



Var
long Temp1, Temp2
byte Master, ID




Pub Initialize
i2c.Initialize( SCL )
Get_Eeprom


Pub Main
{{Run code}}



Pub Get_Eeprom
{{Pay close attention to the numbers 1,4 a 1 = byte and a 4 = long}}


readIt(32_703,@Master,1)
readIt(32_702,@ID,1)
readIt(32_604,@Temp1,4)
readIt(32_600,@Temp2,4)


Pub Set_Eeprom

writeIt(32_703,@Master,1)
writeIt(32_702,@ID,1)
writeIt(32_604,@Temp1,4)
writeIt(32_600,@Temp2,4)




Pub readIt (address, Data, type)


IF i2c.ReadPage(SCL, EEPROM, Address, Data, type)
Abort


Pub writeIt(Address, Data, type) | startTime


IF i2c.WritePage(SCL, EEPROM, Address, Data, type)
Abort
startTime := cnt
repeat while i2c.WriteWait(SCL, EEPROM, Address)
if cnt - startTime > clkfreq / 10
Abort

Bits
10-23-2011, 04:41 PM
Well I have tried to post this a few different ways and yet I am unable to do so. I have attached the code.
86250

Can someone let me in on the secret of placing a code example. I though it was the [ code ] and [ / code ]?

PJ Allen
10-23-2011, 04:49 PM
The secret:

type code, inside brackets
copy and paste (as text) the "code" to be posted
type /code, inside brackets

Bits
10-23-2011, 04:56 PM
That is what I figured yet it still failed to list it. I suppose it has something to do with whats in my code. Perhaps a symbol is causing the problem.

ElectricAye
10-23-2011, 04:57 PM
That is what I figured yet it still failed to list it. I suppose it has something to do with whats in my code. Perhaps a symbol is causing the problem.

This is the same thing PJ suggested, but Phil Pilgrim made a nice link to it that you can share with others for future reference:

http://forums.parallax.com/attachment.php?attachmentid=78421&d=1297987572 (http://forums.parallax.com/showthread.php?129690&p=978076&viewfull=1#post9780 76)

PJ Allen
10-23-2011, 05:45 PM
There shouldn't be any spaces between code and its brackets, likewise /code and its brackets.

Find more secrets --> http://forums.parallax.com/misc.php?do=bbcode

Bits
10-23-2011, 07:10 PM
I will try again


Var


long Temp1, Temp2
byte Master, ID

Pub Initialize


i2c.Initialize(SCL)
Get_Eeprom
main

Pub Main
{{Run code}}



Pub Get_Eeprom
{{Pay close attention to the numbers 1,4 a 1 = byte and a 4 = long}}


readIt(32_703,@Master,1)
readIt(32_702,@ID,1)
readIt(32_604,@Temp1,4)
readIt(32_600,@Temp2,4)


Pub Set_Eeprom
{{ use this during run time to store new variables in eeprom }}
writeIt(32_703,@Master,1)
writeIt(32_702,@ID,1)
writeIt(32_604,@Temp1,4)
writeIt(32_600,@Temp2,4)


Pub readIt(address, Data, type)


IF i2c.ReadPage(SCL, EEPROM, Address, Data, type)
Abort


Pub writeIt(Address, Data, type) | startTime


IF i2c.WritePage(SCL, EEPROM, Address, Data, type)
Abort
startTime := cnt
repeat while i2c.WriteWait(SCL, EEPROM, Address)
if cnt - startTime > clkfreq / 10
Abort