Saving to EEPROM
Joms
Posts: 279
OK, I have been trying to get this to work for awhile now, but don't think I have a complete understanding of how this is supposed to work. To get back to basics, I have been looking at some code that Terry @ Hitt Consulting wrote and it uses a I2C object that he wrote, but looks very similar to others.
I did search a few different topics with the search function, but did not come up with any concrete examples of how this works. So, if someone knows where to point me, that would be GREAT!...
So, to learn this, I modified these few parts of code that I can call on. Basically what I made is a public that when I write to the EEPROM it will take 1 serial input that is a 0-7 (memory slot), then 6 bytes to store a six digit number. Eventually I will try to do more then this, but this is just to help me get the understanding of how this works.
The EEPROM read part should just take the input of 0-7 for the memory slot and return the 6 bytes stored.
Can someone explain where I am going wrong? I am not exactly sure what the 'I2C.i2cWrite($A2 8) line does....if someone could explain what I am writing here?
Post Edited (Joms) : 3/23/2010 7:36:25 PM GMT
I did search a few different topics with the search function, but did not come up with any concrete examples of how this works. So, if someone knows where to point me, that would be GREAT!...
So, to learn this, I modified these few parts of code that I can call on. Basically what I made is a public that when I write to the EEPROM it will take 1 serial input that is a 0-7 (memory slot), then 6 bytes to store a six digit number. Eventually I will try to do more then this, but this is just to help me get the understanding of how this works.
The EEPROM read part should just take the input of 0-7 for the memory slot and return the 6 bytes stored.
Can someone explain where I am going wrong? I am not exactly sure what the 'I2C.i2cWrite($A2 8) line does....if someone could explain what I am writing here?
PUB SaveToEEPROM | pos, addr, i pos:=Serial.GetChar 'Set memory position Repeat i from 0 to 5 'Input 6 bytes of data tempStr[noparse][[/noparse]i][i] := Serial.GetChar 'Store data to tempString [/i] [i][/i]
EDIT - ADDED Debug tempStr here for testing, and working properly to this point.[i][/i]
addr:=32528 + (pos) * 16 'Set address position I2C.Init(28, 29, $A0) 'Init I2C Object using EEPROM pins I2C.i2cStart 'Start the I2C Object IF addr < 65536 I2C.i2cWrite($A0, 8) ELSE I2C.i2cWrite($A2, 8) I2C.i2cWrite((addr / 256), 8) I2C.i2cWrite((addr // 256), 8) REPEAT i FROM 0 TO 5 I2C.i2cWrite(tempStr[noparse][[/noparse]i][i], 8) tempStr[noparse][[/noparse]i][i]:=tempStr[noparse][[/noparse]i][i] ^ 255 IF (addr & $FF) == $FF I2C.i2cStop WAITCNT(400000 + cnt) 'Wait 5mSec I2C.i2cStart IF (addr+1) < 65536 I2C.i2cWrite($A0, 8) ELSE I2C.i2cWrite($A2, 8) I2C.i2cWrite(((addr+1) / 256), 8) I2C.i2cWrite(((addr+1) // 256), 8) addr+=1 I2C.i2cStop WAITCNT(400000 + cnt) 'Wait 5mSec REPEAT i FROM 0 TO 5 tempStr[noparse][[/noparse]i][i]:=tempStr[noparse][[/noparse]i][i] ^ 255 PUB LoadFromEEPROM(pos) | addr, i addr:=32528 + (pos) * 16 'Set address position I2C.Init(28, 29, $A0) 'Init I2C Object using EEPROM pins I2C.i2cStart 'Start the I2C Object IF addr < 65536 I2C.i2cWrite($A0, 8) ELSE I2C.i2cWrite($A2, 8) I2C.i2cWrite(addr / 256, 8) I2C.i2cWrite(addr // 256, 8) I2C.i2cStart I2C.i2cWrite($A1, 8) REPEAT i FROM 0 TO 5 tempStr[noparse][[/noparse]i][i]:=I2C.i2cRead(0, 8) I2C.i2cStop [/i][/i][/i][/i][/i][/i]
Post Edited (Joms) : 3/23/2010 7:36:25 PM GMT
Comments
1. 32528 address space. This would be the same as 7F10 in hex, so, does that directly relate to the memory map on the RAM usage? My program only takes up 1450 longs, so I just went down the list a ways a picked something near the end and thats how I arrived at this number. I assume that 7FF0 (32752) would be the limit of 32K EEPROM. (I am using the prop demo board eeprom.) Is this a correct statement to make? Am I correct in saying it is only a few bytes from the limit, but should allow me to store around 30 bytes of data?
2. Does that number directly correspond to a byte? Basically I could store a byte in 32528, another one in 32529, another one in 32530, and so on?
3. Is there a basic guide on how to write to an EEProm? What I am wondering is a sheet the better describes in what order to write the data and in what format. Like first send a $A0, assuming this is an address for the IC memory, then byte address, then data, and so on. Does anything like this exist?
Sorry for so many questions about this. It just seems like every time I try to write something to the EEPROM I am always pulling my hair out figuring out what is going on. I am looking to get a complete understanding and maybe put together a guide to make this easier for people to learn, as I cant seem to find anything about this...
Thanks for the help in advance...
I've taken a look at your code and I'm not entirely sure what's wrong here, there are a lot of 'suspect' bits but without knowing what you're trying to do I can't say they're wrong.
Some things to note:
1. If you're using a 24LC256 (32KB) chip the data sheet is here www.microchip.com/wwwproducts/Devices.aspx?dDocName=en010823, this covers all the byte transitions etc. Google for 24LC512 if you're using a 64KB chip.
2. Have you really got two 64KB i2c eeproms in your circuit?
3. I think you may be right about the top of RAM being at 32752 (top 4 longs are locks??) since 2^15 = 32KB = 32768 bytes. But the top of RAM in prop is used for the spin stack so even if you are loading the image from eeprom to these locations, chances are the stack will have overwritten it by the time you've got to reading it.
4. Did you try the read/write location functions in the example object you posted.
(Just in case, I doubt this is the problem: 5. Finally, there's no chance the eeprom is write protected? Probably not if you're booting from it as you would then not be able to program it.)
EDIT:
I don't think you need to call the Init subroutine twice, you should do that in your main spin start pub and not in each of the read/write ones.
Basically what I am trying to do is just get this little program working before implementing it into my other program. All I am trying to do is store like 6-8 different bytes to the eeprom then read them after a power cycle. I can attach the entire code, but there really isn't much more then the two publics that I already posted. Basically I am just calling to save a byte with the write public, then reading it and debugging it with the read public. I do have a 1 second delay between write/read, but all I receive is a 'zero' in return when I attempt to read.
1. I have been looking at a sheet very close to that, just not completely sure I understand it. From what I am gathering, the $A0 is the Control Byte, then the two address bytes, then the data byte. I am using the 32kb ic that is on the prop demo board.
2. Nope, just one 32k eeprom, the one that is already on the prop demo board. Since I only need to store 8 bytes of data, I figured I could find a little extra room on there to store the data.
3. I know I am about to ask this without reading the prop manual, but I will pull that out right after I post this and update you if I find any new info. I am hoping to find a memory map of what is free in the 32k memory for general use.
4. I did try that read/write with the example I have posted. I also have been playing around with different addresses with no luck. Actually I picked address 1 knowing it would over-write part of my program, but just thought I would give it a try.
5. I don't think the EEProm is write protected as I am loading it with F11 from the prop tool. I assume there is a pin that sets that, but again, I will check the data sheet for that.
Im not good at explaining things with few words, lol, but hopefully you understand what Im trying to do...
When I am inputing the serial data, it will input as a charactor, not a decimal like I should have been inputing. Basically where I screwed up, is I needed to put ' - "0" ' behind any input to convert it to a decimal.
This has caught me many times before, but I completely overlooked the simple problems in this oops. Guess I can overcomplicate anything...lol
So, that leaves me with this question...
Where is the best place on the included 32k EEPROM to store a few bits of data where it won't get over-written or in the way of other programming? I am assuming the highest available spot right below stack? If so, where is that?
If you're only using one 32K eeprom you shouldn't need the IF addr < 65536 statements, only the first will ever be true, the else statement writing $A2 is addressing a second EEPROM chip on the i2c bus, it won't really hurt if you never let addr be bigger than 32767 but it will slow your code down a bit.
I believe if you declare a variable in spin, then the hub address of that variable can be used as an address for accessing the eeprom. The content of that location will be loaded to that part of HUB at boot as there is a one-to-one relationship between bytes in the EEPROM and HUB.
So if you want to save 8 bytes, declare a variable in your vars section as byte something[noparse][[/noparse]8], then find the address with the @ operator. So;
So you are effectively initialising a for the next boot of the chip. Of course you can always read it back by passing the address of a to the read function.
Note, I've been really bad here and posted untested code, absolutely no guarantee this will work at all, I don't have a prop handy to test it right now.
So every time you reset the propeller, or turn off and on again the value of incb will increment and decb will decrement. Note, because you're using a memory address in the 32K map they are loaded automatically at boot time, no need to read them back manually.
Hope this helps.
P.S. you'll probably need to change the tv object name, it's the standard tv_text object from Parallax, but I live in the UK so switched it to PAL and renamed it.
I didn't really understand the writelocation fuction until I seen how you were using it.
Thanks again and I hope someone else can also learn from this example too. I was WAY over complicating writing to the EEProm...
So, if you have continuous data to write you should write pages or at least all bytes in a row (like in the first post) without starting a new write cycle.
I think the problem in the first post is that paging is done with a wrong page-size.
"if adr & $ff" is for detecting the page wrap. But this only works if the page is really 256 bytes in size. I'd expect something like 32 or 64 bytes. What the page-size of your EEPROM is can be found in the datasheet of the EEPROM you use.
You could have a look at femtoBASIC. This includes a SimpleI2C object and has some code which writes pages.
Post Edited (MagIO2) : 3/24/2010 1:45:05 PM GMT