Results 1 to 9 of 9

Thread: OpenCM 9.04 eeprom write problem

  1. OpenCM 9.04 eeprom write problem

    Hi Guys,
    i'm experiencing a weird problem using the opencm eeprom library.

    With this simple test code:

    Code:
    #include "EEPROM.h"
    int i = 0;
    EEPROM CM_EEPROM;
    
    void setup(){  
      SerialUSB.println ( "Setup" );
      CM_EEPROM.begin();
    }
    
    void loop(){
      delay(10);
      i++;
      SerialUSB.println ( i );
      CM_EEPROM.write(i,i*2);// write i*2 to virtual address 0~9
    }
    when i reaches 256 the opencm restarts from setup(). After some restarts it hangs definitevely.

    What I did wrong?
    Thanks
    L

  2. #2

    Re: OpenCM 9.04 eeprom write problem

    "i" has a value range that can go way beyond the addressable range of the EEPROM library.
    (The EEPROM library is actually emulated by using flash memory.)
    You are writing too much to the EEPROM, outside the supported area.
    Additionally, flash memory has a limited number of write cycles. Writing 100 times a second will go through a 10,000 cycle rated flash in less than two minutes, after which the flash may start suffering write failures.

  3. Re: OpenCM 9.04 eeprom write problem

    Quote Originally Posted by jwatte View Post
    "i" has a value range that can go way beyond the addressable range of the EEPROM library.
    (The EEPROM library is actually emulated by using flash memory.)
    You are writing too much to the EEPROM, outside the supported area.
    Additionally, flash memory has a limited number of write cycles. Writing 100 times a second will go through a 10,000 cycle rated flash in less than two minutes, after which the flash may start suffering write failures.
    You are right, this is on for testing purposes. I've tried with normal usage and it hangs anyway.
    As I've understood looking at utility folder inside eeprom library, two page of 1kB of flash memory is allocated for emulating eeprom. Having a look at eeprom_core.* files it has and hardcoded limit of 510 virtual address (opencm never reached it as it hangs before) that it right because the two pages usa a 4byte block for writing virtual address (2bytes) and content (2bytes) and a 2 byte block is used to store the page's tag.
    The system seems to iterate in pages and sets pages' tags to understand if it can you or not that page.
    The opencm hangs (as i can understand) when it reaches the upper limit of page and tries to use other pages (this seems to confirm that the bug happen at 256 write cycle).
    I've tried to understand something more, but i didn't find anything really wrong. Anyway i don't' understand why who wrote this code cycles in continously in both pages for writing and reading, but this can be my fault.

    Any idea?

    L

  4. #4

    Re: OpenCM 9.04 eeprom write problem

    The STM chip on the OpenCM doesn't have "true" EEPROM memory. Instead, it has page-erasable flash memory. Page-erasable flash memory supports two operations:
    1) Set all the bits of a page to the value 1.
    2) Clear some number of bits to 0.
    Note that there is no way to set a bit back to the value 1, without setting (erasing) the entire page to 1.
    This means that there's no such thing as overwriting only a single byte or a few words in a flash page.

    Now, developers largely want an API where they can say "the value for ID x should be y" without having to worry about whether that value has some "1" bits in places where the previous value had "0" bits.
    Thus, the charade in the system where it treats flash pages as a write log, and re-constructs the latest-available-value per key-index by inspecting the log.

    The other thing to notice is that it's the process of fliping a bit value that wears on flash. Thus, if you do a lot of erase cycles, you will wear the flash down, and it will fail. The STM internal flash is intended for one-time programming of firmware/data, not for logging of often-changing values, so a program that continually writes/erases the flash will end up wearing it out very quickly.

  5. Re: OpenCM 9.04 eeprom write problem

    Quote Originally Posted by jwatte View Post
    The STM chip on the OpenCM doesn't have "true" EEPROM memory. Instead, it has page-erasable flash memory. Page-erasable flash memory supports two operations:
    1) Set all the bits of a page to the value 1.
    2) Clear some number of bits to 0.
    Note that there is no way to set a bit back to the value 1, without setting (erasing) the entire page to 1.
    This means that there's no such thing as overwriting only a single byte or a few words in a flash page.

    Now, developers largely want an API where they can say "the value for ID x should be y" without having to worry about whether that value has some "1" bits in places where the previous value had "0" bits.
    Thus, the charade in the system where it treats flash pages as a write log, and re-constructs the latest-available-value per key-index by inspecting the log.

    The other thing to notice is that it's the process of fliping a bit value that wears on flash. Thus, if you do a lot of erase cycles, you will wear the flash down, and it will fail. The STM internal flash is intended for one-time programming of firmware/data, not for logging of often-changing values, so a program that continually writes/erases the flash will end up wearing it out very quickly.
    Hi,
    it's now more clear. But the problem remains. Just try to write once 350 vaddress with values. It will hang.
    I'm not trying to use the eeprom simulation as a storage, i just need to write it only few time. But if I try to write it more than 256 values in a single run session, it will hang. My previous example was on for triggering the hang not for normale use.

    This is the production code:

    Code:
    int StorageEEprom::saveConfiguration ()
    {
            Configuration current;
            this->loadConfiguration ( &current );
            debug.debug ( "StorageEEprom::saveConfiguration()" );
            if ( this->eeprom == NULL )
            {       
                    debug.debug ( "StorageEEprom::saveConfiguration(): no eeprom object" );
                    return -1;
            
            }
            int eeprom_data[40];
    
    
            for ( int i = 0; i < 40; i++ )
            {       
                    eeprom_data[i] = 0xffff;
            }
    
    
            if ( current.controlProtocol != this->configuration.controlProtocol )
            {       
                    eeprom_data[0] = this->configuration.controlProtocol;
            }
            if ( current.controlDevice != this->configuration.controlDevice )
            {       
                    eeprom_data[1] = this->configuration.controlDevice;
            }
            if ( current.controlSpeed != this->configuration.controlSpeed )
            {       
                    eeprom_data[2] = this->configuration.controlSpeed;
            }
            if ( current.lensProtocol != this->configuration.lensProtocol )
            {       
                    eeprom_data[3] = this->configuration.lensProtocol;
            }
            if ( current.lensDevice != this->configuration.lensDevice )
            {
                    eeprom_data[4] = this->configuration.lensDevice;
            }
            if ( current.lensSpeed != this->configuration.lensSpeed )
            {
                    eeprom_data[5] = this->configuration.lensSpeed;
            }
            if ( current.ptConfiguration.ptProtocol != this->configuration.ptConfiguration.ptProtocol )
            {       
                    eeprom_data[6] = this->configuration.ptConfiguration.ptProtocol;
            }
            if ( current.ptConfiguration.ptDevice != this->configuration.ptConfiguration.ptDevice )
            {       
                    eeprom_data[7] = this->configuration.ptConfiguration.ptDevice;
            }
            if ( current.ptConfiguration.ptType != this->configuration.ptConfiguration.ptType )
            {       
                    eeprom_data[8] = this->configuration.ptConfiguration.ptType;
            }
            eeprom_data[9] = this->configuration.ptConfiguration.panServoId;
            eeprom_data[10] = this->configuration.ptConfiguration.tiltServoId;
            eeprom_data[11] = this->configuration.ptConfiguration.panServoId;
            eeprom_data[12] = this->configuration.ptConfiguration.tiltServoId;
            eeprom_data[15] = this->configuration.ptConfiguration.panMotorEnablePin;
            eeprom_data[16] = this->configuration.ptConfiguration.panMotorPin1;
            eeprom_data[17] = this->configuration.ptConfiguration.panMotorPin2;
            eeprom_data[18] = this->configuration.ptConfiguration.panMotorPWM;
            eeprom_data[20] = this->configuration.ptConfiguration.tiltMotorEnablePin;
            eeprom_data[21] = this->configuration.ptConfiguration.tiltMotorPin1;
            eeprom_data[22] = this->configuration.ptConfiguration.tiltMotorPin2;
            eeprom_data[23] = this->configuration.ptConfiguration.tiltMotorPWM;
            eeprom_data[24] = this->configuration.ptConfiguration.maxMotorRun;
            eeprom_data[25] = this->configuration.ptConfiguration.minPan;
            eeprom_data[26] = this->configuration.ptConfiguration.maxPan;
            eeprom_data[27] = this->configuration.ptConfiguration.minTilt;
            eeprom_data[28] = this->configuration.ptConfiguration.maxTilt;
         
           
            for ( int i = 0; i < 40; i++ )
            {
                    if ( eeprom_data[i] != -1 && eeprom_data[i] < 0xffff )
                    {
                            debug.debug ( "PTZStorageEEprom::saveConfiguration(): address %d %d", this->base_address + i, eeprom_data[i] );
                            this->eeprom->write(this->base_address + i, eeprom_data[i]);
                    }
            }
            return 0;
    }
    It is called only one configuration change. But calling so that it writes more than 256 times it will crash.
    Any ideas?
    Thanks.

  6. #6

    Re: OpenCM 9.04 eeprom write problem

    A few years ago, I ended up trying to fix the bugs in the EEPROM module, but instead just wrote my own based on the same ideas.
    For example, if I only need a handful of different value keys, and each value only needs to be a byte, I can store more values per page and make the page-roll-over code much easier.
    If I remember correctly, there is one or two places in the code that can be updated to actually make it work "as intended" if all you want to do is to fix the existing API, but you'd have to actually make that fix in the support code of the library itself.

  7. Re: OpenCM 9.04 eeprom write problem

    Quote Originally Posted by jwatte View Post
    A few years ago, I ended up trying to fix the bugs in the EEPROM module, but instead just wrote my own based on the same ideas.
    For example, if I only need a handful of different value keys, and each value only needs to be a byte, I can store more values per page and make the page-roll-over code much easier.
    If I remember correctly, there is one or two places in the code that can be updated to actually make it work "as intended" if all you want to do is to fix the existing API, but you'd have to actually make that fix in the support code of the library itself.
    jwatte, thanks for the answer.
    I've tried debugging the support code, but I didn't get anything yet.
    Could you give some hints (or example code) for writing a new library? I could write use the entire page as the write that are needed are really few.

    Thanks in advance.

  8. #8

    Re: OpenCM 9.04 eeprom write problem

    Uh... it's been a while :-)

    If you read the support library, there are two functions that matter, that come from the lower-level flash control library for the MCU:

    1) Clear page
    2) Write to bytes within page

    What you should know is that "clear page" means "set all bits of the entire page to 1" and "write to bytes" really means "mask the zero bits of the target byte to the bits that are zero in the byte written."
    Thus, if you want to update a value, and it so happens that the new value don't set any bits not already set in the old value (but may clear some bits,) that can be done in-place without a page clear.

    The approach, then, is to do something like:
    - define "keys" as values between 1 and 254
    - define "values" as bytes between 0 and 255
    - define the page header as a 16-bit generation number, starting at 0; initialize one page generation to 0 and the other to 1
    - when starting up, figure out which page is the newer (check the sign of the difference between the two pages, accounting for roll-over from ffff -> 0000)
    - when reading, scan through the pairs of <id, value> in the active page, and remember the last value encountered for the given id
    - when writing, simply append a <id, value> pair at the end of the page
    - if the page is full and a write comes in, you have to "compact":
    - clear the previous-oldest (inactive) page
    - determine the value of each existing key
    - write each of those values to the new page -- note, if there are multiple tuples in the old page, just write the newest (latest) one
    - update the generation number of the new page to N+1

    If you have RAM to spare, you can read in the page in start-up (using a "is set" bit for values that are seen,) and serve read requests straight out of an array of 254 bytes (or however many values you want to support.) When writing, update the in-RAM array, and then write a log entry <id, value> to the page. When compacting, just re-write the values that are set in RAM

    There are other ways to solve this, too, but that's how I would do it. The general gist is to avoid erasing flash pages as much as possible, beause that's what actually wears out the flash.

  9. Re: OpenCM 9.04 eeprom write problem

    Hi jwatte,
    thank you very much for hints.
    I used them to write my own module with static mapped configuration in page 126 (i'm not using page 127).
    So I've not pseudo eeprom usage, but it works well now.

    Thanks
    L

Thread Information

Users Browsing this Thread

There are currently 2 users browsing this thread. (0 members and 2 guests)

Similar Threads

  1. Replies: 0
    Last Post: 01-29-2017, 08:33 AM
  2. DARwIn-OP Based Robot Dynamixel EEPROM Values
    By vehemens in forum Humanoids, Walkers & Crawlers
    Replies: 1
    Last Post: 10-23-2016, 08:59 PM
  3. AX12A sync write
    By DVS in forum DYNAMIXEL & Robot Actuators
    Replies: 5
    Last Post: 08-14-2013, 09:15 PM
  4. Question using EEPROM
    By brian25 in forum Software and Programming
    Replies: 1
    Last Post: 08-14-2013, 12:20 AM
  5. Interesting Write LMR challenge
    By Xan in forum Robotics General Discussion
    Replies: 6
    Last Post: 09-16-2008, 11:10 AM

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •