Shop OBEX P1 Docs P2 Docs Learn Events
Help with external memory paged writes — Parallax Forums

Help with external memory paged writes

average joeaverage joe Posts: 795
edited 2014-12-02 23:48 in Propeller 1
Here's my problem. I'm working on some code for external memory and got stumped. The memory is written to in 256 byte pages. If I want to write more than 256 bytes at a time, or start in the middle of the page and write past the end I need to do multiple transfers. I'm thinking detecting one of these cases should be easy. Something like this:
if (memoryaddress & $FF) + count > $100
 ' do extended write

I just can't figure out the fastest way to handle the extended write. This probably isn't the best description but hopefully someone can point me in the right direction.

Comments

  • kwinnkwinn Posts: 8,697
    edited 2014-11-27 21:05
    How to do the extended write will depend on the type of memory you are using.

    For determining how to do the extended write you need to determine what cases need to be handled. The cases may include full page, less than full page, more than full page, starting at beginning of page, and starting mid-page. That could be a lot of cases.

    Perhaps you can buffer the data so it only gets written once you have a full page.
  • GenetixGenetix Posts: 1,754
    edited 2014-11-29 13:56
    What EEPROM are you using?
    JonnyMac wrote some very nice objects that includes a method called Page_Num which returns the page number for an address and another one called Page_OK which tells you if an address range fits in one page. There is a method called Copy_To that writes a byte at a time and another called Copy_From that reads a byte at a time.

    There are several notes in the Object saying, "-- be mindful of address/page size in device to prevent page wrap-around".
  • average joeaverage joe Posts: 795
    edited 2014-11-29 15:24
    Thanks for your response guys.

    @kwinn - It would be nice to be able to call one method that covers every case you mentioned. I came here for ideas because that's a lot of edge cases to cover and I'm still troubleshooting other code.

    @Genetix - I think I have JM's eeprom object somewhere. I'll look through it and see if anything sparks some ideas. I'm actually using several different memories, for several different purposes. I have a 1MB i2c boot eeprom (AT24CM01), 64MB SPI FLASH(W25Q64VSIG) and 256KB SPI nvSRAM (CY14B256Q2A). I have the flash (and of course EEPROM) working for normal writes (ie not wrapping pages)

    I did have some difficulties with the FLASH and SRAM. Fried a bunch of chips (still scratching my head as to why) and waiting for more SRAMs before continuing breadboard testing.

    Any help would be amazing!
  • average joeaverage joe Posts: 795
    edited 2014-12-02 05:59
    I've finally bumped into the first case I need to handle. This is when the data entry is less than a full page and crosses the page wrap. I sat down and tried to write it up and this is what I came up with:
    PUB WriteBytesFlash(chipAddress,dataPtr,number)  | cah, cal, t1, t2
        if (chipAddress & cons#_page_size + number) > cons#_page_size  ' check for page wrap
          cah := chipAddress & cons#_add_high                          ' save high bytes of address
          cal := chipAddress & cons#_page_size                         ' save low bytes of address
          t1  := cons#_page_size - cal                                 ' number of bytes before address wrap
          t2  := number - t1                                           ' number of bytes after address wrap
          DoFlashWrite(cah + 1, dataPtr + t1, t2)                      ' write data after wrap  
        else
          t1 := number                                                 ' move number to t1
        DoFlashWrite(chipAddress, dataPtr, t1)                         ' write data before wrap
    

    This seems a bit bulky, considering it won't handle an entry that wraps twice. What am I missing?
  • kwinnkwinn Posts: 8,697
    edited 2014-12-02 08:10
    Have you considered reading and writing full pages only. That is for writing partial pages read the full page, fill in the new data, write the page out. Repeat for data that spans two pages. It may be a bit slower but IIRC not by much since full page reads and writes are faster than partial read/writes. It also reduces the number of special cases to (1) write beginning to mid point, (2) write mid to mid points, (3) write mid point to end. Writing large blocks would be a combination of 3, Possibly full page writes, and 1.
  • average joeaverage joe Posts: 795
    edited 2014-12-02 08:34
    kwinn wrote: »
    Have you considered reading and writing full pages only. That is for writing partial pages read the full page, fill in the new data, write the page out. Repeat for data that spans two pages. It may be a bit slower but IIRC not by much since full page reads and writes are faster than partial read/writes. It also reduces the number of special cases to (1) write beginning to mid point, (2) write mid to mid points, (3) write mid point to end. Writing large blocks would be a combination of 3, Possibly full page writes, and 1.

    I had initially thought about it but this project requires 0 data loss. The only edge case where data loss is acceptable is if the propeller loses power between receiving a packet and handling said packet. Also, I'm worried about memory overhead. I'm already close to 80% of propeller memory full and much code left to write. There is also the issue that I can't guarantee a full page will be written. There are several types of data, stored across multiple segments of memory. Speed is not too much of an issue but code density is.
  • kwinnkwinn Posts: 8,697
    edited 2014-12-02 12:06
    Thanks for your response guys.........

    I'm actually using several different memories, for several different purposes. I have a 1MB i2c boot eeprom (AT24CM01), 64MB SPI FLASH(W25Q64VSIG) and 256KB SPI nvSRAM (CY14B256Q2A). I have the flash (and of course EEPROM) working for normal writes (ie not wrapping pages) ........

    Perhaps if you post a general description of how you are handling the incoming data we could provide better suggestions. I'm guessing here but it seems like you may be using the SRAM as a data buffer to hold the incoming data until the entire packet is received and then writing it to the 64MB flash chip. Is this the case?
  • Dave HeinDave Hein Posts: 6,347
    edited 2014-12-02 13:16
    I think this code will handle the general case where you could have 0, 1 or more page wraps.
    CON
      pagesize = cons#_page_size
      pagemask = pagesize - 1
    
    PUB WriteBytesFlash(chipAddr, dataPtr, number) | len
      repeat while number > 0
        len := pagesize - (chipAddr & pagemask) <# number
        DoFlashWrite(chipAddr, dataPtr, len)
        chipAddr += len
        dataPtr += len
        number -= len
    
    EDIT: I'm assuming cons#_page_size is the size of the page in bytes, and is a power of 2. However, it appears from your code that cons#_page_size is actually 1 less than the number of bytes. If that is true then the constants pagesize and pagemask would need to be adjusted accordingly.
  • average joeaverage joe Posts: 795
    edited 2014-12-02 23:48
    Dave Hein wrote: »
    I think this code will handle the general case where you could have 0, 1 or more page wraps.
    CON
      pagesize = cons#_page_size
      pagemask = pagesize - 1
    
    PUB WriteBytesFlash(chipAddr, dataPtr, number) | len
      repeat while number > 0
        len := pagesize - (chipAddr & pagemask) <# number
        DoFlashWrite(chipAddr, dataPtr, len)
        chipAddr += len
        dataPtr += len
        number -= len
    
    EDIT: I'm assuming cons#_page_size is the size of the page in bytes, and is a power of 2. However, it appears from your code that cons#_page_size is actually 1 less than the number of bytes. If that is true then the constants pagesize and pagemask would need to be adjusted accordingly.

    Thanks Dave!
    len := pagesize - (chipAddr & pagemask) <# number that's exactly what I was looking for!
Sign In or Register to comment.