Shop OBEX P1 Docs P2 Docs Learn Events
Trouble using Basic_i2c_Driver — Parallax Forums

Trouble using Basic_i2c_Driver

Marc GebauerMarc Gebauer Posts: 60
edited 2007-07-08 03:41 in Propeller 1
Help! I have a problem writing to the boot EEPROM. I have 2 - 320 byte variable arrays that I want to save thier·content·to the equivilant locations on the boot EEPROM, so on reboot they will load with those values.

So you know... I also have·8 pcf8574's·on the·same i2c bus·via·+5 to 3.3v level shifter (see attached schematic exerpt). I am able to read and write to these devices reliably using the Basic_i2c_Driver.·Also, I have tested·both variable arrays·to see that the·data really exsists and is valid·before I try and write·them·to EEPROM. FYI I have seen this same code work on this same board, yet it does not now. When I was originally testing this routine, the first varible array·data did not write reliably, while the second variable array·data did. I figured that I had a bad eeprom and changed it. Then it worked! I was able to save to both variables 320 byte arrays and the data came back. I thought I had fixed it. Now I am coming to to point where I am finishing my program and I went to test my 'save' routine and it's failing again,·with both variables·smhair.gif.·Another test I've done is,·I·write the same content into both variable's EEPRON locations·and they both don't come back the same.·I don't think I am damaging the EEPROM, because when I reload my program into the EEPROM(F11), those location get zero'd perfectly and my program·uploads perfectly.··The datasheet says that this device is capable of 1,000,000 write cycles. I've only run my·'save' routine 20 times at the most.

I'm stumped...

Here is a sample of the code I am using to save my variables to EEPROM.

I write 10-32 byte pages for 320 bytes of information,·I don't get·any naks, yet what I write does not·come back when I reboot prop.


*** CODE ***
VAR

byte config_mem1[noparse][[/noparse]320], config_mem2[noparse][[/noparse]320]


PUB start

flags := writeNVmem(@config_mem1)·· 'write 10 - 32 byte pages


PRI writeNVmem(ptr) : nak | i, startTime
''Write 10 - 32 byte pages to the variable's loction in· eeprom memory
· nak~
· repeat i from 0 to 9
··· if i2c.WritePage(i2c#BootPin, i2c#EEPROM, ptr+32*i,ptr+32*i,32)
····· nak := 1
····· abort ' an error occured during the write
··· startTime := cnt ' prepare to check for a timeout
··· repeat while i2c.WriteWait(i2c#BootPin, i2c#EEPROM, ptr+32*i)
····· if cnt - startTime > clkfreq / 10
······· nak := 1
······· abort ' waited more than a 1/10 second for the write to finish


▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔


Post Edited (Marc Gebauer) : 7/7/2007 4:22:33 AM GMT

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2007-06-30 14:16
    From what you've posted it ought to work. I've used a combination of PCF9554 with a 24LC512, but running the PCF9554 off 3.3V without the level shifter. It seems like it isn't the hardware since you've gotten it to work earlier and there's not enough of your program to see if there's something subtly wrong elsewhere. Do you have some kind of debug display so you can see the contents of config_mem1 before writing and when restarting the program?
  • Marc GebauerMarc Gebauer Posts: 60
    edited 2007-07-05 20:48
    Mike,

    I have written a test program that, via a write button in my GUI,·copies 320 bytes of source data stored in the DAT area to a 320 byte array. Then it compares whats in the array to the source data to make sure the data is the same.·After that·it writes·the array·to·it's equivilent location in EEPROM memory. At this point my program instructs you to press RESET and after reset it compares the source data with the array. So far I have no luck. What am I doing wrong?

    By the way my program requires a VGA monitor and mouse and runs on demo board.

    I have tried this on Demo board, Education kit and my own PCB and none of them work.

    Also, the EEPROM I am using is the microchip 24LC256 on my PCB




    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔


    Post Edited (Marc Gebauer) : 7/5/2007 9:09:41 PM GMT
  • Mike GreenMike Green Posts: 23,101
    edited 2007-07-06 03:52
    Marc,
    The EEPROM pages are multiples of the EEPROM's page size which is 64 bytes for the Microchip 24LC256 devices. Since you're trying to store the data into an VAR array and the array may span a 64 byte page boundary, it may not write properly (the EEPROM wraps the internal buffer address at the 64 byte boundary. You could either use some memory at the end of the hub address space (like $8000-320 through $7FFF) for this data or write it to the EEPROM one byte at a time which will be slower, but will for sure work.
  • Marc GebauerMarc Gebauer Posts: 60
    edited 2007-07-06 04:32
    Thanks Mike. I see what you mean.

    I like the idea of assigning my array an address·that is aligned·with the·64 byte boundries and still doing page writes. This is great I can't wait to try it out. I'll let you know how it goes.

    Thanks again. Your awsome.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
  • Marc GebauerMarc Gebauer Posts: 60
    edited 2007-07-06 17:11
    It worked!

    I want to give back, so I wrote the following routine that takes in account the page boundries when writing to·an EEPROM. They may not be the most optimized code.·I just wanted to make it work.

    <<< The Code >>>
    OBJ
    · i2c·········· : "Basic_i2c_Driver"

    PRI writeEEPROM(eepromAddress,sourcePtr,numBytes,pageSize) : err | i, numBytesToNextBoundry, remainingBytes, remainingPages
    ''Write a var/array at the source pointer in ram to an EEPROM at the destination address,
    ''compensating for·the EEPROM's page boundries.
    ' note: make pageSize the EEPROM's page buffer size or a multiple of the EEPROM's page buffer size
    · numBytesToNextBoundry := (pageSize - eepromAddress // pageSize) // pageSize
    · if numBytesToNextBoundry < numBytes
    ··· 'there are more bytes to be written than the number of bytes to the next boundry.
    ··· if numBytesToNextBoundry
    ····· 'eepromAddress is not on a page boundry, write bytes up to boundry
    ····· if err := writeIt(eepromAddress, sourcePtr, numBytesToNextBoundry)
    ······· abort ' an error occured during the write·························
    ··· remainingBytes := numBytes - numBytesToNextBoundry
    ··· remainingPages := remainingBytes/pageSize
    ··· if remainingPages
    ····· 'there are pages of bytes to be written
    ····· repeat i from 0 to remainingPages
    ······· 'write pages without overwriting the scope of the bytes to be written
    ······· if err := writeIt((eepromAddress+numBytesToNextBoundry)+i*pageSize, (sourcePtr+numBytesToNextBoundry)+i*pageSize, pageSize)
    ········· abort ' an error occured during the write·························
    ····· remainingBytes -= remainingPages*pageSize
    · else
    ··· 'the number of bytes to be written do not cross EEPROM page boundry
    ··· remainingBytes := numBytes·
    · if remainingBytes
    ··· 'write remaining bytes
    ··· if err := writeIt(eepromAddress+numBytes-remainingBytes, sourcePtr+numBytes-remainingBytes, remainingBytes)·
    ····· abort ' an error occured during the write·························
    ·
    ·


    PRI writeIt(eepromAddress, sourcePtr, numBytes) : err | startTime
    ''modified writeIt routine from example in Basic_i2c_Driver.spin
    · if err := i2c.WritePage(i2c#BootPin, i2c#EEPROM, eepromAddress, sourcePtr, numBytes)
    ··· abort ' an error occured during the write·························
    · startTime := cnt ' prepare to check for a timeout···················
    · repeat while i2c.WriteWait(i2c#BootPin, i2c#EEPROM, eepromAddress)··
    ··· if cnt - startTime > clkfreq / 10·································
    ····· err := true
    ····· abort ' waited more than a 1/10 second for the write to finish··

    ·

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔


    Post Edited (Marc Gebauer) : 7/8/2007 9:16:23 PM GMT
  • Marc GebauerMarc Gebauer Posts: 60
    edited 2007-07-08 03:41
    Came up with a much more efficient way, than·posted above,·to·write and·read large numbers of bytes·to and from an·EEPROM·via Basic_i2c_Driver. These routines calculate the number of bytes to·the next·page boundry or multiple·of the page boundry size.


    OBJ
    · i2c·········· : "Basic_i2c_Driver"

    PRI WriteEEPROM(eepromAddress, sourceAddress, numBytes, pageSize) : err | writePageSize, startTime
    ''Write a number of bytes to an EEPROM, at eepromAddress from a variable or array at sourceAddress.
    ' This routine calculates the write page size so that it fits within the EEPROM page boundries.
    ' * Must set pageSize to the EEPROM's page buffer size or a multiple of the EEPROM's page buffer size.

    · repeat while numBytes· 'write to EEPROM until done

    ··· 'calculate number of bytes to the next boundry and
    ··· 'limit value used by the number of bytes to be written.
    ··· writePageSize := (pageSize - eepromAddress // pageSize) <# numBytes··

    ··· 'write it
    ··· if err := i2c.WritePage(i2c#BootPin, i2c#EEPROM, eepromAddress, sourceAddress, writePageSize)
    ····· abort ' an error occured during the write·························
    ··· startTime := cnt ' prepare to check for a timeout···················
    ··· repeat while i2c.WriteWait(i2c#BootPin, i2c#EEPROM, eepromAddress)··
    ····· if cnt - startTime > clkfreq / 10·································
    ······· err := true
    ······· abort ' waited more than a 1/10 second for the write to finish··

    ··· numBytes -= writePageSize······ 'update remaining bytes
    ··· eepromAddress += writePageSize· 'update address
    ··· sourceAddress += writePageSize· 'update address
    ···
    ·
    PRI ReadEEPROM(destAddress, eepromAddress, numBytes, pageSize) : ackbit | readPageSize
    ''Read a number of bytes from an EEPROM at eepromAddress to a variable or array at destAddress.
    ' This routine calculates the read page size so that it fits within the EEPROM page boundries.
    ' * Must set pageSize to the EEPROM's page buffer size or a multiple of the EEPROM's page buffer size.

    · repeat while numBytes· 'read from EEPROM until done

    ··· 'calculate number of bytes to the next boundry and
    ··· 'limit value used by the number of bytes to be read.
    ··· readPageSize := (pageSize - eepromAddress // pageSize) <# numBytes··

    ··· 'read it
    ··· if ackbit := i2c.ReadPage(i2c#BootPin, i2c#EEPROM, eepromAddress, destAddress, readPageSize)
    ····· abort ' an error occurred during the read

    ··· numBytes -= readPageSize······· 'update remaining bytes
    ··· destAddress += readPageSize···· 'update address············
    ··· eepromAddress += readPageSize·· 'update address············
    ···
    ·


    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔


    Post Edited (Marc Gebauer) : 7/8/2007 2:26:19 PM GMT
Sign In or Register to comment.