PDA

View Full Version : Solved Writing data to EEPROM



JBWolf
11-02-2011, 02:28 PM
-=UPDATE=-
Solved! See last posts for example code.
Works with the 24LC256 that comes with the PEKit




Hello,
I am having a little trouble figuring out how to write data to eeprom for the first time.
I have the 32k included with the PEKit, I only need to write maybe four variables of byte length.
I would like to keep these values so the program will 'remember' settings after being turned off.
Not sure how I write the data, or how to make sure there is enough room.

All help is appreciated :)
J

Mike Green
11-02-2011, 02:35 PM
Using the "Basic_I2C_Driver" object from the ObEx, you'd write a value to the variable X as follows: (from the comments in Basic_I2C_Driver)
PRI writeIt( value ) | startTime
if i2c.WritePage(i2c#BootPin, i2c#EEPROM, @X, @value, 1)
abort ' an error occured during the write
startTime := cnt ' prepare to check for a timeout
repeat while i2c.WriteWait(i2c#BootPin, i2c#EEPROM, @X)
if cnt - startTime > clkfreq / 10
abort ' waited more than a 1/10 second for the write to finish

JBWolf
11-02-2011, 06:25 PM
Is that object compatible with this eeprom? In the description is listed several eeprom model numbers, none of which match the one included with the PE kit.
http://www.parallax.com/Store/Components/AllIntegratedCircuits/tabid/154/CategoryID/18/List/0/SortField/0/Level/a/ProductID/400/Default.aspx

Here is the object I think you are referring to:
http://obex.parallax.com/objects/251/

Bobb Fwed
11-02-2011, 06:28 PM
It's this object: http://obex.parallax.com/objects/672/

That object is compatible with (just about) any EEPROM that works with the Propeller.

Rayman
11-02-2011, 06:54 PM
Maybe something like this is what you want:
http://forums.parallax.com/showthrea...ogging-and-I2C (http://forums.parallax.com/showthread.php?97625-PE-Kit-Lab-Applications-%96-EEPROM-Datalogging-and-I2C)

4x5n
11-02-2011, 09:40 PM
Maybe something like this is what you want:
http://forums.parallax.com/showthrea...ogging-and-I2C (http://forums.parallax.com/showthread.php?97625-PE-Kit-Lab-Applications-%96-EEPROM-Datalogging-and-I2C)



I had to spend some time thinking about how to use it but Mike's Basic_I2C_driver works great and is nice and small. I put together a short program to demo reading and writing to eeprom using his driver. I selected an address beyond 32K so be sure to change the start address so the data will fit.



''This my first attempt at writing a program to use
''the Basic_I2C_Driver to read and write to an eeprom
''above the 32KB boundary Since it's only a test I made
''no attempt to prompt for the data to write.
''The constant EEPROMaddress is the start address
''The constant Writechar is the data to be written to the eeprom


CON
_clkmode = xtal1 + pll16x 'Standard clock mode * crystal frequency = 80 MHz
_xinfreq = 5_000_000

EEPROM = %1010_0000
EEPROMaddress = $9000
I2cSCL = 28

Writechar = $ff

VAR
long eaddr, eeval

OBJ
ee : "Basic_I2C_Driver"
pst : "Parallax Serial Terminal"

PUB main

' Initialize serial terminal and i2c driver
pst.Start(115200)
ee.Initialize(I2cSCL)

' Delay for five seconds
repeat 10

pst.char(".")
waitcnt(clkfreq/2+cnt)

pst.NewLine

' Read 16 bytes of data and output to serial terminal
readee

pst.Newline

' Write 16 bytes of data don't bother outputing to serial terminal
writeee

' Read data just written. Hopefully it will have the proper data
readee

' Announce completion :-)
pst.str(string("quiting now"))


PUB readee

eaddr := EEPROMaddress
pst.str(string("Reading eeprom"))
pst.NewLine

repeat 16

pst.str(string("Reading address: 0x"))
pst.Hex(eaddr, 4)
eeval := ee.ReadByte(I2cSCL, EEPROM, eaddr)
pst.str(string(" - "))
pst.Hex(eeval, 2)
pst.NewLine
eaddr++

PUB writeee

eaddr := EEPROMaddress

pst.str(string("Writing to eeprom"))
pst.NewLine
pst.NewLine

repeat 16

ee.WriteByte(I2cSCL, EEPROM, eaddr, Writechar)
eaddr++

[
Finding the space to put it is up to you but you could use the propeller spin tool to find unused eeprom space. Keep in mind that if you use eeprom space in the lower 32K space the data will be overwritten every time you use the propeller tool to program the eeprom.

Bobb Fwed
11-02-2011, 09:47 PM
If you don't care about using up a fair bit of memory (doing something pretty simple), I have something that will handle everything for you and manage any size and type of values: Memory Storage Management Lightweight (http://obex.parallax.com/objects/671/) (or the larger, more flexible Memory Storage Management (http://obex.parallax.com/objects/493/)).

JBWolf
11-19-2011, 11:29 AM
Thanks for the replies, Sorry for the delay in responding.

Ok I just spent a few hours trying to get one to work...
First I tried:
http://forums.parallax.com/showthread.php?97625-PE-Kit-Lab-Applications-%96-EEPROM-Datalogging-and-I2C
This seemed like a simple to use object, but everytime I try to use VarBackup, the whole program locks up.
I tried the most simple approach I could think of...
program starts, VAR long value[31], initialize 'value' to 0.
Use pushbutton to increase value.
eeprom.varbackup(@value, @value[31] + 3)
program locks

Next I took a look at:
Memory Storage Management Lightweight (http://obex.parallax.com/objects/671/)
But I couldnt even figure out what commands to use for backing up and restoring, that and the memory addresses were so confusing that I gave up.

Tomorrow I will take a look at:
http://obex.parallax.com/objects/672/

If I cannot get anything going from that either, I will post some code and hopefully someone will have the time to walk me through
I appreciate the help!

JBWolf
11-19-2011, 11:42 AM
Ok I went ahead and took a peek at the basic I2C and couldnt get past here:
This will work with the boot EEPROM and does not require a pull-up
resistor on the SCL line (but does on the SDA line ... about 4.7K to
+3.3V)

Does this mean I need to add a resistor?
Sorry, I have absolutely no previous knowledge in this area at all.... Very confusing to me.

lardom
11-19-2011, 06:01 PM
Martin Hebel has an object called "BS2_Functions" in the OBEX which I find easy to use. One useful insight is that variables occupy the same address in ROM as they do in RAM. This means you can store a new value in a variable then write to and read from the eeprom by the variable name as opposed to a hex address. "variablename @variablename". The object has several 'read' and 'write' methods which you might find helpful.

Mike Green
11-19-2011, 06:28 PM
All I2C devices require that there be a pull-up resistor on the SDA and SCL lines, usually near the "bus master" which, in this case, is the Propeller. If you don't use certain features of the I2C specification (like multiple bus masters) you can get away with only one pull-up on the SDA line. Most Propeller boards only provide the pull-up resistor on the SDA line. The I/O driver has to be written to support this and the Basic_I2C object supports this. It will also work with an I2C bus with a pull-up on both lines.

Duane Degn
11-19-2011, 09:51 PM
Most Propeller boards only provide the pull-up resistor on the SDA line.

Mike,

I disagree. I think the norm is for Propeller boards to use pull-ups on both the data and clock lines. I recently looked (http://forums.parallax.com/showthread.php?131538-50-TetraProp(tm)-Boards-now-ready-to-ship-!&p=1044614&viewfull=1#post1044614)through some of my Propeller boards to note which boards use a pull-up on the clock and which don't.

I found three boards without pull-ups on both lines.

The Propeller Professional Development board
Propeller Demo Board
Jazzed's TetraProp board (He says leaving off the clock pull-up was an oversight.)

These are the boards with pull-ups on both lines.

Propeller Protoboards
QuickStart boards
GG Propeller Platform
Spinneret
Laser Range Finder
Propeller Backpack
Hydra
Tubular's UN3RB3LLY

Kye's real time clock object assumes there are pull-ups on both lines.

Duane

localroger
11-19-2011, 10:38 PM
Both the PPDB and DemoBoard are first generation products where a little short-sighted thinking, later corrected, might have applied.

JBWolf
11-20-2011, 12:07 AM
I am using the PEkit 40-pin dip... just the bare parts on one of my protoboards (model 203a).

So to use any of these objects, do I need to add a special resistor?
How do I identify which resistor I need to purchase and how exactly should I connect it? (i typically purchase through digikey)

I need this in lamens terms with walkthrough... I did not get any useable info from posts 10-13

Something simple like... to write to eeprom for the first time, you will first need to purchase one of these and place it here orientated like this.
Then download this object. Here is a simple example of how to use this object. here are the commands for this object and how to use them.

I need a very clear and formal learning method. I am getting nothing but bits and pieces with lots of assumed stuff.
I havent really learned a single thing yet about how to do this properly, and do not feel any closer... I'm amazed this hasnt been addressed yet

lardom
11-20-2011, 05:40 AM
You begin with a parts list and a schematic. If you have the PE kit chapter three will show you how to connect the eeprom.

Duane Degn
11-20-2011, 06:08 AM
do I need to add a special resistor?
How do I identify which resistor I need to purchase and how exactly should I connect it? (i typically purchase through digikey)

I need this in lamens terms with walkthrough... I did not get any useable info from posts 10-13


. . .

and do not feel any closer... I'm amazed this hasnt been addressed yet

The sticky thread at the top of the Propeller Forum titled "Propeller Education Kit, Labs, Tools and Applications" list additional labs, tools and applications to use with the PEK. One lab is "EEPROM Datalogging". Here's the thread (http://forums.parallax.com/showthread.php?97625-PE-Kit-Lab-Applications-–-EEPROM-Datalogging-and-I2C&p=678271#post678271).

A 10K resistor has the color bands brown, black, orange and either gold or silver.

Most of the schematics of the boards listed in post #12 (one without useful information) are available to download. They will show how the resistors are connected (the Hydra schematic is a bit different than the rest).

JBWolf
11-20-2011, 06:55 AM
I do have a working propeller as per the PEkit instructions along with a working program.
I need to backup several long variables, they are to be restored after power is turned back on.

I have tried using Here's the thread. (http://forums.parallax.com/showthread.php?97625-PE-Kit-Lab-Applications-–-EEPROM-Datalogging-and-I2C&p=678271#post678271) but it does not mention anything about needing an extra pull-up resistor.
As there is no mention to changing hardware, and says it is designed to work with the 24LC256 that comes with the PEKit, I tried using the program as is.
I only used the 'propeller eeprom.spin' object as I do not need hyperterminal.
I used the code as illustrated, but my program immediately locks up when it reaches the eeprom.varbackup call.
I will post my code below in a bit

JBWolf
11-20-2011, 08:04 AM
Ok I had to improvise as my code is way way too long to post in here just for the sake of debugging the databackup.
I basically cut and revised to make it as basic as possible.

General program structure:
One cog monitors buttons, other works with LED.
pushing button increases speed of blinking led.

One problem that I am trying to address by creating a 'databackup' indicator... is when the program is run for the first time, there will be nothing to restore.
So I put an IF statement in to create default variables if the databackup value is < 1
Everytime either the speed or counter variable is changed, it needs to set the databackup variable to 1 and backup both.
On next reboot, the system should start by recovering the 'databackup' variable first, then recover both the speed & counter variable


{{

mem backup test

}}


CON

Button1 = 21
Button2 = 20
LED = 26


OBJ
eeprom : "Propeller Eeprom"

VAR

long stack[50]
byte cog[5]
long counter[31]
long speed[31]
long databackup[31]



PUB Main

eeprom.VarRestore(@databackup, @databackup[31] + 3) ' restore databackup indicator

if databackup < 1
speed := 100 ' set defaults if databackup < 1
counter := 5
else
eeprom.VarRestore(@counter, @counter[31] + 3) ' restore variables if databackup = 1
eeprom.VarRestore(@speed, @speed[31] + 3)

launch2cogs
repeat


PUB Launch2cogs

coginit(3, Buttons(@counter, @databackup), @stack[10])
coginit(4, Blink(@speed, @counter, @databackup), @stack[20])


PUB Buttons(CounterAddress, dbackup) | tmp
dira[button1]~
dira[button2]~


tmp := long[CounterAddress] ' temp counter variable

repeat
if button1 == 1 and button2 == 1 ' hold both buttons for system reset with default variables
long[dbackup] := 0 ' turn off backup indicator
eeprom.VarBackup(@dbackup, @dbackup[31] + 3) ' backup the indicator value
REBOOT ' restart prop

if button1 == 1 and button2 == 0
tmp := ++tmp // 4 ' if button pressed, increment temp counter
long[counteraddress] := tmp ' write new counter value
long[dbackup] := 1 ' write databackup indicator
eeprom.VarBackup(@counteraddress, @counteraddress[31] + 3) ' backup new counter variable
eeprom.VarBackup(@dbackup, @dbackup[31] + 3) ' backup the indicator
waitcnt(clkfreq + cnt) ' wait 1 sec




PUB Blink(SpeedAddress, counteraddress, dbackup) | tmp1, tmp2
dira[LED]~~
outa[LED]~~
tmp1 := 0 ' temp counter variable
tmp2 := 0 ' temp speed variable

repeat
if long[counteraddress] <> tmp1 ' if counter variable has changed since last loop
tmp1 := long[counteraddress] ' tmp1 grabs new counter value
repeat tmp1 ' loop 'counter' many times
case tmp1 ' set speed variable based on counter value
0 : tmp2 := 100
1 : tmp2 := 200
2 : tmp2 := 300
3 : tmp2 := 400
4 : tmp2 := 500
!outa[LED] ' flop the LED outa condition
waitcnt(clkfreq / tmp2 + cnt) ' wait 1 sec / speed
!outa[LED] ' flop the LED outa condition

long[speedaddress] := tmp2 ' write new speed value
eeprom.VarBackup(@speedaddress, @speedaddress[31] + 3) ' backup new speed variable
eeprom.VarBackup(@dbackup, @dbackup[31] + 3) ' create backup indicator
waitcnt(clkfreq + cnt)




The program will not run, it locks up immediately

lardom
11-20-2011, 04:19 PM
This is the logic in one of my working methods. I use a 4x4 keypad and I programmed the letter "D" to make a method call;

PUB NewDistance hypothetical method
keypad := 0 clear the keypad so I can use it for other operations
IF (some conditional statement)
Distance := 0 reset the value so I can change it
Distance := New value input from keypad PRI method
(display the new value on my lcd)
BS2.Write_CodeMem(@Distance,Distance,2) Martin Hebel's object writes to the eeprom
New value := 0 clear the variable so I can use it for other operations

I hope this helps.

Mike Green
11-20-2011, 04:38 PM
I suspect that your program is locking up because you're calling eeprom.VarBackup from two cogs at the same time. The routines involved wait for various conditions to occur and, because both cogs are trying to access the EEPROM (and the I/O pins involved) at the same time, one of them is hanging up and maybe causing the other to hang up as well.

Any time two different cogs can access a shared resource, like specific I/O pins or the same hub variables, at the same time, you have to use a lock or semaphore. In Spin, these are provided with the LOCKxxx statements. Somewhere in your program's initialization, you have to get a lock id with:

lockId := LOCKNEW ' lockId is a global long variable

Before each call to eeprom.VarBackup, you need to have a

REPEAT UNTIL NOT LOCKSET(lockId)

After each call to eeprom.VarBackup, you need to have a

LOCKCLR(lockId)

JBWolf
11-20-2011, 11:00 PM
Mike, I tried exactly as you instructed... same result, locks up
I added some debugging to the LED so I can generally tell where it is locking up by having the LED flash at the beginning of the cogs being launched.
It does blink the LED indicating the cogs have been launched.
In the program, the Buttons routine backs up 2 variables after a button is pressed. In the Blink routine it is supposed to blink the LED depending on the button being pressed... it never gets this far.
So it must be locking up while trying to write the variables in the Buttons routine.

Here is my attempt at your instructions:
Can you correct my code? I normally dont ask for others to write my code as it skips the learning step... but I would LOVE to see a working example.
I am just getting so frustrated with this


{{

mem backup test

}}


CON

Button1 = 21
Button2 = 20
LED = 26


OBJ
eeprom : "Eeprom"

VAR

long stack[50]
byte cog[5]
long counter[31]
long speed[31]
long databackup[31]
long lockid


PUB Main
dira[26]~~
outa[26] := 1
waitcnt(clkfreq + cnt)

lockId := LOCKNEW

eeprom.VarRestore(@databackup, @databackup[31] + 3) ' restore databackup indicator

if databackup < 1
speed := 100 ' set defaults if databackup < 1
counter := 5
else
eeprom.VarRestore(@counter, @counter[31] + 3) ' restore variables if databackup = 1
eeprom.VarRestore(@speed, @speed[31] + 3)
outa[26] := 0
waitcnt(clkfreq + cnt)
launch2cogs
repeat


PUB Launch2cogs

coginit(3, Buttons(@counter, @databackup), @stack[10])
coginit(4, Blink(@speed, @counter, @databackup), @stack[20])


PUB Buttons(CounterAddress, dbackup) | tmp
dira[button1]~
dira[button2]~


tmp := long[CounterAddress] ' temp counter variable

repeat
if ina[button1] == 1 and ina[button2] == 1 ' hold both buttons for system reset with default variables
long[dbackup] := 0 ' turn off backup indicator
REPEAT UNTIL NOT LOCKSET(lockId)
eeprom.VarBackup(@dbackup, @dbackup[31] + 3) ' backup the indicator value
LOCKCLR(lockId)
REBOOT ' restart prop

if ina[button1] == 1 and ina[button2] == 0
tmp := ++tmp // 4 ' if button pressed, increment temp counter
long[counteraddress] := tmp ' write new counter value
long[dbackup] := 1 ' write databackup indicator
REPEAT UNTIL NOT LOCKSET(lockId)
eeprom.VarBackup(@counteraddress, @counteraddress[31] + 3) ' backup new counter variable
LOCKCLR(lockId)
REPEAT UNTIL NOT LOCKSET(lockId)
eeprom.VarBackup(@dbackup, @dbackup[31] + 3) ' backup the indicator
LOCKCLR(lockId)
waitcnt(clkfreq + cnt) ' wait 1 sec




PUB Blink(SpeedAddress, counteraddress, dbackup) | tmp1, tmp2
dira[LED]~~
outa[LED]~~
waitcnt(clkfreq /2 + cnt)
outa[LED]~
waitcnt(clkfreq /2 + cnt)
tmp1 := 0 ' temp counter variable
tmp2 := 0 ' temp speed variable

repeat
if long[counteraddress] <> tmp1 ' if counter variable has changed since last loop
tmp1 := long[counteraddress] ' tmp1 grabs new counter value
repeat tmp1 ' loop 'counter' many times
case tmp1 ' set speed variable based on counter value
0 : tmp2 := 100
1 : tmp2 := 200
2 : tmp2 := 300
3 : tmp2 := 400
4 : tmp2 := 500
!outa[LED] ' flop the LED outa condition
waitcnt(clkfreq / tmp2 + cnt) ' wait 1 sec / speed
!outa[LED] ' flop the LED outa condition

long[speedaddress] := tmp2 ' write new speed value
REPEAT UNTIL NOT LOCKSET(lockId)
eeprom.VarBackup(@speedaddress, @speedaddress[31] + 3) ' backup new speed variable
LOCKCLR(lockId)
REPEAT UNTIL NOT LOCKSET(lockId)
eeprom.VarBackup(@dbackup, @dbackup[31] + 3) ' create backup indicator
LOCKCLR(lockId)
waitcnt(clkfreq + cnt)

kuroneko
11-21-2011, 12:07 AM
@JBWolf: FWIW, your first restore operation basically kills your lockid. databackup is defined as having 31 longs (0..30) but you restore 32 longs. If you go back to the PE Kit thread you'll notice that they actually use 32 longs for their data arrays. Other arrays suffer from the same issue. Also, 10 longs for a SPIN stack (@stack[10]..@stack[20]) is rather small. I'd suggest - given that you reserve 50 longs initially - @stack{0} and @stack[25] respectively.

re: lock usage, don't indent your to-be-protected code under the lockset line. This (indentation) simply means it's called until the lock is required which is what you want to avoid. Have a look at the manual (v1.2, p.126) LOCKSET + examples.


repeat while lockset(ID)
write(parameter) ' don't indent this code
lockclr(ID)

lardom
11-21-2011, 04:11 AM
I hope I'm seeing this correctly. Your led goes out after "outa[26] := 0". Two lines below that you write "launch2cogs" and then "repeat" is indented below that. I would comment that last command out.
One of the debugging techniques that I use is to add code that displays values or strings to the PST. A debug statement that will display the values in "speed" and "counter" at any given point is more conclusive than an led.

JBWolf
11-22-2011, 05:28 AM
Larry, yes I understand adding a PST would reveal more information than an LED. But the problem is the program locks up when it reaches the VarBackup.... so knowing the value isn't going to help me. If I remove the VarBackup, everything works fine, so I'm not very concerned about the values so much as finding where exactly in the program it locks up at. Right now it is locking up in the Button method when it reaches the VarBackup command. If I can get the VarBackup & VarRestore to work, the LED should blink the number of times the variable value is, basically providing me the same debugging as a pst. But if you think it will help, I will certainly add a pst

Kuro:
Ok I will increase the stack. What should I do about the arrays?

One thing I dont understand about the 'propeller eeprom.spin' object is the start address and end address.
I used value[31] as demonstrated in their documentation, I was assuming that was to get an end value, i.e. - VarBackup(@value, @value[31])
In other words, if there is only one variable without an array, the beginning address would be the same as the end address... therefore nothing.
Am I assuming this wrong? Can I simply use a VarBackup(@value, @value) so properly backup the value?

kuroneko
11-22-2011, 05:44 AM
What should I do about the arrays?

One thing I dont understand about the 'propeller eeprom.spin' object is the start address and end address.
I used value[31] as demonstrated in their documentation, I was assuming that was to get an end value, i.e. - VarBackup(@value, @value[31])
In other words, if there is only one variable without an array, the beginning address would be the same as the end address... therefore nothing.
Am I assuming this wrong? Can I simply use a VarBackup(@value, @value) so properly backup the value?

They define the array with 32 longs (you only used 31). Meaning the last element of this (32 long) array is value[31] (first being value[0]). Getting its address will effectively return the address of its first byte which is where the +3 comes in. So if you want to save a single long you'd call

eeprom.VarBackup(@value, @value+3)

Did you adjust your lock code?

Just noticed something else. You should get your address/value contexts sorted out. E.g. you pass the address of the speed (array) to your blink method but in there you use the address of the parameter (@speedaddress). In this case you just want speedaddress. It would also be a good idea to keep the reboot command inside the lock.

FWIW, I came up with a minimal test case but it locks up for some reason.

kuroneko
11-22-2011, 06:56 AM
FWIW, I came up with a minimal test case but it locks up for some reason.
This EEPROM object doesn't play nicely with multiple cogs regardless of whether you use locks or not. Once e.g. a VarRestore finishes it pulls the clock line high (I2cStop method) in the context of the current cog. Which means another cog can never control the clock line. A solution would be to delegate the EEPROM handling to a single cog (and let other cogs talk to it). Does that fit into your plans?

JBWolf
11-22-2011, 07:16 AM
Ok yes I think I can do that... since the main cog0 is not doing anything after launching the other cogs, I can have this monitor a variable that tells it to backup to eeprom.

I decided to make it even more simple for the sake of learning:


{{

mem backup test

}}


CON

Button1 = 21
Button2 = 20
LED = 26


OBJ
eeprom : "Eeprom"

VAR

long stack[300]
byte cog[5]
long counter
long speed


PUB Main

counter := 0
speed := 0

launch2cogs
repeat


PUB Launch2cogs

coginit(3, Buttons(@counter, @speed), @stack[50])
coginit(4, Blink(@counter, @speed), @stack[100])


PUB Buttons(count, spd) | tmp1, tmp2
dira[button1]~
dira[button2]~


tmp1 := 4 ' temp counter variable
tmp2 := 4

repeat
if ina[button1] == 1
tmp1 := ++tmp1 //5
long[count] := tmp1

if ina[button2] == 1
tmp2 := ++tmp2 //5
long[spd] := tmp2
waitcnt(clkfreq /5 + cnt)




PUB Blink(count, spd) | tmp1, tmp2, tmp3
dira[LED]~~
outa[LED]~~
tmp1 := 0 ' temp counter variable
tmp2 := 0 ' temp speed variable
tmp3 := 0


repeat
tmp1 := long[count]
tmp2 := long[spd]
tmp3 := tmp2 * 2 + 2
repeat (tmp1 + 1 * 2)
!outa[LED]
waitcnt(clkfreq / tmp3 + cnt)
!outa[LED]
waitcnt(clkfreq / tmp3 + cnt)
waitcnt(clkfreq + cnt)

Ill edit this in a bit to try to get a backup to work.
do I need to include the locks?
Do I need to have a 31 array variable for varbackup to find the end address?

kuroneko
11-22-2011, 07:24 AM
do I need to include the locks?
Do I need to have a 31 array variable for varbackup to find the end address?
Locks, yes, because you still have multiple users. Delegating the EEPROM handling to a single cog just sidesteps the pin contention.

If you only want to backup single long variables then you don't need an array. Just use @value and @value + 3 or - assuming a function takes its address - value_addr and value_addr + 3. Array backup works like before - assuming value[N] - @value[0] and @value[N-1] + 3.

re: the array thing, a single long is equivalent to using long value[1] which means you'd end up with @value[0] for the start address and @value[1-1] + 3 for the end address. Both address (@) expressions are @value[0] which is the same as @value.

Update: Also note that data transfer between RAM and EEPROM is byte oriented. So you should be careful re: reading/updating variables while they are being restored/backed up. For example bytes 0 and 1 of a given long are written to EEPROM then another cog updates said long (atomic op) and then we finish with bytes 2 and 3 (of the new value). Which isn't necessarily what you want.

JBWolf
11-22-2011, 08:11 AM
ITS ALIVE!
This code works, remembers settings even after powerdown



{{

mem backup test
2 buttons, 1 led
button 1 increases blink speed
button 2 increases blink amount

}}


CON

Button1 = 21
Button2 = 20
LED = 26


OBJ
eeprom : "Eeprom"

VAR

long stack[300]
byte cog[2]
long counter
long speed
long databackup
long indicator
long blank[0]


PUB Main


eeprom.VarRestore(@counter, @blank - 1)
waitcnt(clkfreq / 2 + cnt)

if indicator < 1
counter := 0
speed := 0
indicator := 0
databackup := 0


launch2cogs

repeat
if databackup := 1
databackup := 0
indicator := 1
eeprom.VarBackup(@counter, @blank - 1) ' restore variables if databackup = 1
waitcnt(clkfreq / 5 + cnt)


PUB Launch2cogs

coginit(3, Buttons(@counter, @speed, @databackup), @stack[50])
coginit(4, Blink(@counter, @speed), @stack[100])


PUB Buttons(count, spd, dbackup) | tmp1, tmp2
dira~
dira~


tmp1 := long[count]
tmp2 := long[spd]


repeat
if ina[button1] == 1
tmp1 := ++tmp1 //5
long[count] := tmp1
long[dbackup] := 1

if ina[button2] == 1
tmp2 := ++tmp2 //5
long[spd] := tmp2
long[dbackup] := 1
waitcnt(clkfreq /4 + cnt)




PUB Blink(count, spd) | tmp1, tmp2, tmp3
dira[LED]~~
outa[LED]~~
tmp1 := 0 ' temp counter variable
tmp2 := 0 ' temp speed variable
tmp3 := 0


repeat
tmp1 := long[count]
tmp2 := long[spd]
tmp3 := tmp2 * 2 + 2
repeat (tmp1 + 1 * 2)
!outa[LED]
waitcnt(clkfreq / tmp3 + cnt)
!outa[LED]
waitcnt(clkfreq / tmp3 + cnt)
waitcnt(clkfreq + cnt)






For anyone else trying to use the eeprom for the first time... im using this object from Andy Lindsay, only the 'propeller eeprom.spin'.
Thread - [B]EEPROM Datalogging and I2C (http://forums.parallax.com/showthread.php?97625-PE-Kit-Lab-Applications-%96-EEPROM-Datalogging-and-I2C)
Object - [B]EEPROM Datalogging and I2C (http://forums.parallax.com/attachment.php?attachmentid=49565)
This code can be used in a public sticky or added to the propeller eeprom docs.spin for first timers like myself.
If this code came as an example with the object, I woulda been sooo happy!

kuroneko
11-22-2011, 08:21 AM
... and try working with single longs.
Backing up a range of variables like you just introduced is perfectly OK. Two minor things, the end address is one too high (use @blank - 1) and you could define it as long blank[0] so it doesn't take up space.

JBWolf
11-22-2011, 08:33 AM
Ok I edited the previous code.
The program still works :)

How much of a delay should I have after a VarBackup or VarRestore command before using again?
Thank you so much for helping me :)

kuroneko
11-22-2011, 01:34 PM
How much of a delay should I have after a VarBackup or VarRestore command before using again?
Up to you. AFAICS there is no specific limit.

One last thing, I'd suggest you defer resetting databackup until after the VarBackup call returns. Then guard your button conditions with something like

if ina[button1] and not databackup
...
This avoids changes to the data while its being backed up (see note in post #28).

JBWolf
11-22-2011, 03:18 PM
Ah I get ya, good thinking... I put in more delays than necessary to avoid just that.
So I do not need any delay between writing variables?
I could have two VarBackup calls back to back without any delay?

I have already finished adding the eeprom backup to my actual program, works great!
I figured out how to backup data nested 2+ cogs deep... so far I have accomplished everything I was hoping to :)
yay!

kuroneko
11-23-2011, 12:06 AM
Yes, any number of VarBackup calls is possible without delay (additionally, the guard I suggested should probably only be around the actual backup call so that you at least update your variable during a button press). Note, the example you posted only does a backup in the context of a single cog. Once you start backing up from more than one cog you have to synchronise them somehow. I'm sure you'll figure it out, it's all in this thread.

lardom
11-23-2011, 12:24 AM
Kuroneko, excellent. BTW today I learned how to use bytefill from one of your posts from February this year so I'll say thanks twice in this thread.