Shop OBEX P1 Docs P2 Docs Learn Events
EEPROM direct Read/Write ? — Parallax Forums

EEPROM direct Read/Write ?

Areal PersonAreal Person Posts: 197
edited 2007-11-14 05:34 in Propeller 1
Hi,
I'm trying to get a handle on reading/writing specific EEPROM memory locations.
I'm trying to use the Femento routines.

I've also reviewed the FemtoBasic EEPROM cmd.

But I don't know what I'm doing wrong ?

Can someone help me, it's probly somthing simple stupid
because I'm new to all this stuff.

Here's my code
***********************************

CON
·· _clkmode· = xtal1 + pll16x
·· _xinfreq· = 5_000_000
·
OBJ
···· fsrw· : "fsrwFemto"
···· dsp·· : "vga_drive"

VAR
·
· long ioControl[noparse][[/noparse]2]
· byte ret_buff

DAT
buff····· byte····· "Z"
········
PUB mainProgram

· dsp.start(16)
· fsrw.start(@ioControl)······················· ' Start I2C/SPI driver·

· fsrw.writeEEPROM(28,@buff,1)
· fsrw.readEEPROM(28,@ret_buff,4)

· dsp.hex(byte[noparse][[/noparse]@ret_buff],5)·

*******************************

I've tryed some different things, but I can't get it to work.

Thanks for the help,
-Areal

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
I have a tree growing out of my head, but

what do you expect ? I'm a programmer.

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2007-11-11 06:08
    You have to read the long comment at the beginning of the "sdspiFemto" routines. In particular, read the paragraph that begins "The EEPROM address is in the same format ...". For use with the boot EEPROM, you can just use the constant "fsrw#bootAddr" added to the actual EEPROM address you want to use.

    Don't forget that the EEPROM write cycle takes about 10 milliseconds to finish. Try the following to write/read the end of the 32K boot EEPROM:
    fsrw.writeEEPROM($7FF0 + fsrw#bootAddr, @buff, 1)
    waitcnt(clkfreq / 100 + cnt) ' wait 10ms
    fsrw.readEEPROM($7FF0 + fsrw#bootAddr, @ret_buff, 1)
    


    Note that in your code, you're trying to read 4 bytes into a 1 byte variable.
  • Mike GreenMike Green Posts: 23,101
    edited 2007-11-11 06:13
    There's another routine called writeWait that allows you to wait only long enough for the EEPROM to finish its write since most EEPROMs will finish in less than 10ms. The example I gave would look like this:
    fsrw.writeEEPROM($7FF0 + fsrw#bootAddr, @buff, 1)
    fsrw.writeWait($7FF0 + fsrw#bootAddr)
    fsrw.readEEPROM($7FF0 + fsrw#bootAddr, @ret_buff, 1)
    
  • Areal PersonAreal Person Posts: 197
    edited 2007-11-11 06:22
    Thanks Mike ! It worked first time ! I've been reading so much, I lost my marbles. I did not understand it that way.
    That really helped me to learn somthing [noparse]:)[/noparse]

    Thank you so very much !

    -Areal

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    I have a tree growing out of my head, but

    what do you expect ? I'm a programmer.
  • RaymanRayman Posts: 14,350
    edited 2007-11-11 12:36
    Mike, what's the read speed of your i2c EEPROM code?
  • Mike GreenMike Green Posts: 23,101
    edited 2007-11-11 15:21
    Rayman,
    I haven't really tested it. It was written to run at either 100kHz or 400kHz bus speeds and seems to have intermittent problems at 400kHz (I've never figured out why) so the Spin interface routines always use 100kHz. For large block reads, it ought to achieve 10k bytes per second. For small blocks, the setup overhead (calling the routines, addressing the device, etc.) would sharply cut into this.
  • RaymanRayman Posts: 14,350
    edited 2007-11-11 17:47
    Great. I didn't realize it was that fast... If it can sustain 8kB/s, I could play short WAV clips directly from EEPROM...
  • Areal PersonAreal Person Posts: 197
    edited 2007-11-11 18:32
    Could someone explain this code. I dont understand this shift statment.
    Why use 18 for i2cBootSCL ?

    i2cBootSCL = 28 ' Boot EEPROM SCL pin
    bootAddr = i2cBootSCL << 18 ' Address of boot EEPROM

    QUESTION:

    If I place an EEPROM on a different pin, and I don't want it to be connected to the first one, say... 14
    Would I still use 18 when I shift ?

    I want a second EEPROM, but I do not want it chained from the first one.
    (completly independent from the first boot eepeom)
    E.G

    i2cEEPROM_2_SCL = 14
    EEPROM_2_Addr = i2cEEPROM_2_SCL << 18 ' Address of a different EEPROM


    Or must I use SPI and different read/write routines ?


    -Thanks

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    I have a tree growing out of my head, but

    what do you expect ? I'm a programmer.

    Post Edited (Areal Person) : 11/11/2007 6:43:59 PM GMT
  • Mike GreenMike Green Posts: 23,101
    edited 2007-11-11 19:23
    The I2C and SPI routines will work with pretty much any I/O pins. In the case of I2C, the clock has to be on the lower (even) pin number of a pair and the data has to be on the higher (odd) pin number of a pair of I/O pins. All of this is described in the comments at the beginning of sdspiFemto.spin. The shift positions the pin # correctly. The EEPROM address is considered to be a continuous address space with each I/O pin pair occupying a 512K segment in an 8M address space. Within the 512K segment, you can have up to 8 EEPROM devices, each occupying part or all of a 64K segment. For devices larger than 64K, they appear to be multiple 64K devices.

    As you showed, if you have additional EEPROM on pins 24/25, you use 24 << 18 as part of the address to designate the pins used.
  • Areal PersonAreal Person Posts: 197
    edited 2007-11-11 21:24
    Thanks Mike !

    I've heard talk about an SPI engine ? is that the sdspiFemto.spin file ? Or is there somthing I'm missing ?

    I looked through the Prop OS and found some code that does a transfer of data to/from Vinculum USB Host in SPI mode
    in the osMassStorage.spin file.

    Do I have the SPI Engine, or am I missing somthing ?

    I need to start working with SPI, I've only ever hooked up 1 chip, I think I used SPI to do it?
    It was the TLC5940, I clocked a datastream in and latched it into the register by sending a rising edge of XLAT. (Is that spi ?)


    Thanks for all your help,
    -Areal

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    I have a tree growing out of my head, but

    what do you expect ? I'm a programmer.
  • Mike GreenMike Green Posts: 23,101
    edited 2007-11-11 22:08
    There's an assembly code example of SPI access in one of the "sticky threads" (http://forums.parallax.com/showthread.php?p=601870) that's called the "SPI Engine". It's a general purpose SPI routine based somewhat on the way the Stamps use SPI. The one in the Propeller OS is specific to how the Vinculum USB Host does SPI (3 control bits, then 8 data bits) and was used for experimenting with the Vinculum devices. The main problem is that there's no standard. Different devices do SPI slightly differently. The only thing in common is that they're all clocked serial data protocols using a device select line (low true) to select the device and initiate a data transfer. The SPI code in sdspiFemto.spin is specific for support of SD cards although it may work for some other devices.
  • Areal PersonAreal Person Posts: 197
    edited 2007-11-11 22:21
    Thanks,
    -Areal

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    I have a tree growing out of my head, but

    what do you expect ? I'm a programmer.
  • Areal PersonAreal Person Posts: 197
    edited 2007-11-14 03:33
    @Mike,
    could you give me some advise/pointers on what I'm doing wrong, I CANT GET IT TO WORK
    I tried to setup a different Pin I/O Pair so I can use a second EEPROM
    on my demo board. (I need to use a different pin pair). I understand what you said about the 512 segments
    in the 8meg block per pin I/O pair.

    Does the memory start over at 0000 for each pin pair, or does it continue ?

    I've tried both addresses, could you offer me an address for a second pin I/O pair
    just so I can check it ?

    Also...(I also tryed a fram chip), then went back to a second 24LC256 to keep it simple.

    I did this ...

    24LC256.A0·->·VSS
    24LC256.A1·->·VSS
    24LC256.A2·->·VSS
    24LC256.VSS·->·VSS
    24LC256.VCC·->·3.3vdc
    24LC256.WP·->·VSS
    24LC256.SCL·->·PROP.P2···· (Lower even pin for the clk)
    24LC256.SDA·->·PROP.P3···

    Then, I added this under the bootAddr stuff in sdspiFemto.spin
    ·i2cFram1SCL = 2
    ·Fram1Addr·· = i2cFram1SCL << 18

    I also updated fsrwFemto like this...
    con
    ·· bootAddr· = ldr#bootAddr··· ' Address of boot EEPROM (in I2C address space)
    ·· vbase···· = ldr#vbase······ ' Length of Spin program loaded (# longs * 4)
    ·· Fram1Addr = ldr#Fram1Addr·· '· I ADDED THIS LINE HERE !!!!!!!!!!!!!!!!!!!!!!!!!!!!

    *************************************************
    Then I did this in my spin code.
    The checkPresence function always returns true NO matter what I do.
    *************************************************
    tmp := false
    tmp := fsrw.checkPresence($7FF0 + fsrw#Fram1Addr)
    · if tmp
    ··· dsp.str(string("Found the FRAM chip !"))
    · else
    ··· dsp.str(string(":ERROR: FRAM NOT Found!"))
    · dsp.str(string(" ",13," ",13))··
    ···
    · fsrw.writeEEPROM($7FF0 + fsrw#Fram1Addr, @buff, 1)···· '·I ALSO TRIED $d5ac + fsrw#Fram1Addr ETC...
    · waitcnt(clkfreq / 100 + cnt) ' wait 10ms
    · fsrw.readEEPROM($7FF0 + fsrw#Fram1Addr, @ret_buff, 1)
    · dumpRAM(@ret_buff,4)

    '
    ' THIS FUNCTION WORKS FINE !!
    ' Dump ram memory
    '
    '
    '
    PUB dumpRAM(addr,size) | i, c, p, first, buf0, buf1, buf2
    '' This routine dumps a portion of the RAM/ROM to the display
    '' The format is 8 bytes wide with hexadecimal and ASCII.
    ·· addr &= $7FFFF
    ·· first := true
    ·· p := addr & $7FFF8
    ·· repeat while p < (addr + size)
    ····· if first
    ········ dsp.hex(addr,5)
    ········ first := false
    ····· else
    ········ dsp.hex(p,5)
    ····· dsp.out(":")
    ····· repeat i from 0 to 7
    ········ byte[noparse][[/noparse]@buf0][noparse][[/noparse]i] := " "
    ········ if p => addr and p < (addr + size)
    ·············· c := byte[noparse][[/noparse]p]
    ··········· dsp.hex(c,2)
    ··········· if c => " " and c =< "~"
    ·············· byte[noparse][[/noparse]@buf0][noparse][[/noparse]i] := c
    ········ else
    ··········· dsp.out(" ")
    ··········· dsp.out(" ")
    ········ dsp.out(" ")
    ········ p++
    ····· buf2 := 0
    ····· dsp.out("|")
    ····· dsp.str(@buf0)
    ····· dsp.out("|")
    ····· dsp.out(fReturn)·
    ********************************************************
    Thanks for any help you can offer, I'm trying to learn how to hook
    memory chips.
    -Areal

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    I have a tree growing out of my head, but

    what do you expect ? I'm a programmer.
  • Mike GreenMike Green Posts: 23,101
    edited 2007-11-14 05:34
    Your code looks correct. The FRAM chips will always be present if they're physically and electrically present. Their write cycle is the same speed as their read cycle and there's no "page" limitations. You can write any size block to them and not wait before reading or writing more. The 24LC256 FRAMs are 32K byte devices. Like most 32K EEPROM devices, they ignore the most significant bit of the 16 bit portion of the address, thus the 2nd 32K is the same as the 1st 32K, but all 64K addresses are valid.
Sign In or Register to comment.