Shop Learn
What sort of timing can I expect to read/write upper EEPROM memory locations? — Parallax Forums

What sort of timing can I expect to read/write upper EEPROM memory locations?

I am mystified as to why my read/write timing of upper EEPROM memory locations take so long.

Using SPIN I2C routines I am getting 177ms to read 20 memory locations.

Using PASM I2C routines set to 400,000KHz I am getting 7.8ms to read 20 memory locations.

None of the reads span a page boundary.

These are long times!

I am purposely reading 1 memory location at a time. I can speed things up with multibyte reads/writes, but that is a different use case.

When I read lower memory locations using n := long[@addr], the times are super fast!

Should I expect faster speeds?

Comments

  • JonnyMacJonnyMac Posts: 7,583
    edited 2021-03-03 15:13

    The reason you're seeing the speed difference is that

      n := long[p_data]
    

    ..isn't reading from the EEPROM, it's reading from RAM. When the Propeller boots, the entire contents of the EEPROM (32K) are copied into the RAM. I would suggest you create a RAM buffer in your program for those values stored in the upper EEPROM.

  • Thank you, JonnyMac

    I keep having to remind myself that this the the case. Then, you come along and remind me again. I appreciate it!

    The specification requires the device to record 64 bytes to a FIFO in non-volatile memory every 50ms until an event occurs. Hours may pass before the event occurs. After the event, the device has to record 64 bytes to the FIFO in non-volatile memory every 50ms while emptying the FIFO to an SD card at more than 64 bytes every 50ms. Eventually the FIFO will empty and the SD card will catchup.

    The previous device recorded to a buffer with one cog, and another cog emptied the buffer to a SD card (actually, another 2 cogs, one for fsrw and another for SPI). The desire is to lower the power consumption by recording to a FIFO in non-volatile memory until the event occurs. After the event, the FIFO is written to the SD card and continues to write to the SD card until the process is completed many minutes later. This enables the device to preserve what happened at least 10 seconds before the event, along with data during the event.

    The non-volatile memory is on an i2c bus. The previous device saves configuration data in non-volatile memory, and I used that for FIFO timing measurements. Future devices will use SPI for non-volatile memory. I have to live with i2c for the time being.

    I did timing measurements using jm_i2c.spin, and this is unacceptable. SPIN is too slow.

    I redid timing measurements using jm_i2c_fast.spin, and this is acceptable. PASM is fast enough. Unfortunately, it adds a cog.

    We really don't want to add a cog, but P1 SPIN does not allow inline PASM. We're too close to production to switch to P1 C or P2 now.

    I wrote this post because I thought SPIN i2c would be fast enough, but it's really slow!

  • And yet Tachyon can do all that you need and more and with high speed i2c and over 1MB/s SD write speeds etc out of the same cog as other code.
    Tachyon was developed for commercial projects that had to work and still fit within the confines of the P1 and so your specifications are not even anywhere near a challenge.

  • Oh, yes. Tachyon. I've been following it on the forum. It's downloadable to the P1 now in the P2 ROM. Great work.

    Since jm_i2c_fast works, I'll keep moving forward.

    Thanks for the suggestion!

  • None of the reads span a page boundary.

    --Page boundaries are not a concern for EEPROM reads. Only for writes, especially for multibyte writes.

    The specification requires the device to record 64 bytes to a FIFO in non-volatile memory every 50ms until an event occurs. Hours may pass before the event occurs.

    --Are you trying to write to EEPROM at that rate continuously? Not a good idea in standard EEPROM, wear it out eventually. Also, when writing individual bytes to EEPROM, there is an obligatory dead time of a few milliseconds for the write to complete. Better to write a whole page at once. Why not write the buffer to the fast Propeller RAM, and thence to the SD card when the trigger occurs? The RAM is non-volatile so long as power is applied. Maybe I misunderstood.

    We really don't want to add a cog

    --The penalty is not really that great. With a PASM cog, you will be able to add some WAITxxx states to conserve power until the trigger occurs.

  • Thank you for your advice, Tracy Allen.

    This particular design uses a 128KBx8 F-RAM in lieu of an EEPROM.

    Our design goal is to save 3200 longs until an event occurs. We don't have that much space available. Future designs will store 5 times more.

    The i2c PASM cog adds 8.1mA. Our design goal is to minimize battery drain as much as possible. This is currently our best option so far.

    I used a variety of techniques by uncommenting appropriate lines of code shown below. I intentionally did not compensate for overhead.

      repeat
    
    '    lower memory (RAM)
    '    repeat Watchdog from 0 to 19                       ' 1 long x 1
    '      XRECV := cnt
    '      long[@Buffer1][Watchdog] := Watchdog
    '      n := long[@Buffer1][Watchdog]
    '      XRECV := cnt - XRECV
    '      Face.Str(1,Format.decstr(XRECV,10))
    '      Face.Str(2,Format.hexstr(n,5))
    
    '    upper memory jm_i2c
    '    repeat Watchdog from $8000 to $8013                ' 1 long x 1
    '      XRECV := cnt
    '      ECM.WriteMemLong(Watchdog,Watchdog)             
    '      n := ECM.ReadMemLong(Watchdog)
    '      XRECV := cnt - XRECV
    '      Face.Str(1,Format.decstr(XRECV,10))
    '      Face.Str(2,Format.hexstr(n,5))
    
    '    upper memory jm_i2c_fast
    '    XRECV := cnt
    '    repeat Watchdog from $8000 to $8013                ' 1 long x 20
    '        ECM.WriteMemLong(Watchdog,Watchdog)        
    '        n := ECM.ReadMemLong(Watchdog)
    '    XRECV := cnt - XRECV
    '    Face.Str(1,Format.decstr(XRECV,10))
    '    Face.Str(2,Format.hexstr(n,5))
    
    '   lower memory (RAM)
    '   XRECV := cnt
    '   repeat Watchdog from 0 to 19                        ' 1 long x 20
    '     long[@Buffer1][Watchdog] := Watchdog
    '     n := long[@Buffer1][Watchdog]
    '   XRECV := cnt - XRECV
    '   Face.Str(1,Format.decstr(XRECV,10))
    '   Face.Str(2,Format.hexstr(n,5))
    
    '   upper memory jm_i2c_fast                            ' 20 longs (80 bytes) x 1
        repeat Watchdog from 0 to 79
          byte[@Buffer1][Watchdog] := Watchdog              ' Preload buffer with unique data
        XRECV := cnt
        ECM.WriteMemBlock($8000,@Buffer1,80)                ' wr_block(p_src,count)
        result := ECM.ReadMemBlock($8000,@Buffer1,80)       ' rd_block(p_dest,count,ackbit)
        XRECV := cnt - XRECV
        Face.Str(1,Format.decstr(XRECV,10))
        Face.Str(2,Format.decstr(result,10))
    
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2021-03-11 01:45

    I would just dedicate one large file, up to 4GB and write to it continually as one big buffer flushing it every 50ms. Then you can also write to another file at the same time for your event logs. Now that your buffer is 4GB, it has achieved its own type of wear leveling

    4GB = over 61 million 64 byte records every 50ms = 39 days. Therefore in a year each sector in that 4GB will have been written to 9 times or actually 72 times if we flush every 50ms. Not a problem at all I would think.

    Writing a sector only requires around 2ms or so. But maybe this approach is not so good for battery life perhaps.

  • Peter Jakacki, thank you for your suggestion.

    This is a rugged, battery-powered device.

    We started with your approach. It works well under normal conditions.

    We changed the requirement to close the SD card file every 500ms to minimize data loss in the event of a transient power loss or transient SD card connection loss. Closing the file every 500ms has resolved issues with scrambling the file system on the card.

    True, it's not good for battery life.

    These transients are exceptional and rare, but when transients do occur, the recorded data is exceptionally valuable. Field replaceability requirements constrain our design and force us to avoid soldered batteries and flash memory devices

    We changed the design to record to F-RAM until an event occurs, dump the F-RAM to the SD card and continue to record to the SD card until another event occurs. This considerably shortens the time the SD card has to be drawing power.

    I encourage all suggestions while continue development.

  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2021-03-11 03:25

    This "closing" thing is not necessary as you are performing raw sector writes into a large buffer. Treat it like that and at reset look for an end of buffer marker which is best handled by clearing and marking the next sector to be used when starting the current one and so you look for this marker and back track to the "end-of-buffer". I have used lots of different approaches with logging and the one thing that needs to be avoided is writing to the directory to update the file size or touching the FAT table. That is why if you preallocate one large file then there is no need to do anything else to the FAT or dir entry but treat it as a big buffer. This approach has proved to be very simple and reliable. The SD card draws very little power in standby although I will probably need to go and check to see what that is.

  • Thank you for bringing out a point that I missed. The FAT is not touched after opening the large file.

    We'll consider this for when recording to the SD card.

    Post processing to locate the end of recorded data, which can take some time, can be done off-line or during subsequent data transfer.

    I think you'll find that the current draw writing to a F-RAM is considerably less than an SD card in the hours prior to an event.

  • This is true that FRAM has the advantage of low power but unless the rest of your circuit is also, it is to no great advantage. The advantage of the SD card is that if 4GB holds 38 days of samples, then a 64GB card can hold a whole years worth. One thing I found with storing raw data is that later on if I need to glean more detail, I can. Nothing is wasted and it was all worth it.

    Very early on in one of my projects in the 80's or so, a consulting company asked that I design a traffic counter and they proceeded to specify what constituted a car, a truck, etc. I was puzzled and said, why try to figure that out beforehand and find out later it wasn't quite right. Just record the timestamps and let the reporting software figure out what is what as it needs to. Same too with POS terminals in the 80's, I may have been the first to come up with an "electronic journal" to supplement or replace printed journals and which provided an electronic audit trail, but of course this had to be stored in a very compact format in battery-backed RAM.

    Vending machines also benefited from logging raw events as there were always complaints that the "machine ate my money" etc but the event logs could say something very different. Actually that helped get me out of the doggie doodoo with a rather big and adamant note validator manufacturer and the finally proven inability of the validator's ability to handle curly plastic notes reliability, as Australian notes are.

    Well, you probably know all about logging anyway. I just get so annoyed hearing about how slow and how much resources some objects end up being. I guess that's why I developed and use Tachyon as I don't have any of those problems, and yet it is still the same Prop chip.

  • Ah... not EEPROM but 128kB FRAM! Good idea.

    Some designs that record the calls of bat or birds use SD cards like Peter is suggesting, storing vocalizations to a large pre-formatted empty file. They usually trigger on an event. Being audio, it eats memory pretty fast. So data pre-trigger is stored in RAM. Could be FRAM, but non-volatility shouldn't be a requirement .

    If you need 10 seconds of pre-trigger data taken at 64 bytes per 50 ms, that adds up to 1280 bytes in the ten second buffer. There is plenty of room for that in the 128kB FRAM, or maybe even in the Prop 32kB main RAM. It sounds like the design is still expanding though. You mentioned also 3200 longs (12.8kB) before the trigger. That would still fit with room to grow in FRAM. It would need extra in order to continue buffering while the SD card powers up and catches up. Will you power down the SD card completely between triggers? What is your design target for power? I think SD cards vary widely in quiescent current, from maybe 50 microamps to 1500 microamps.

  • All devices are additive to battery drain. When we can eliminate current draw, we do.

    Our data acquisition requirements are relatively modest. I, too, developed data acquisition and control devices in the 1970s, 80s, 90s and now in the 10s and 20s. I would love to share stories about different applications.

    I was just astounded at how slow SPIN I2C is. PASM I2C meets our requirements.

    I think your P1 and P2 Tachyon are amazing. Over the years I have had some difficulty approaching Tachyon for embedded terminal-less applications. Something about P1 Tachyon eludes me. I have followed your links and many forum posts, but I must not be looking in the right places. Are there reference designs available for P1 Tachyon applications that do not use a terminal? Can a single P1 Tachyon instance collect data from multiple simultaneous I2C buses?

    In our application, the device will be on for a maximum of a day. After turn on, the device sleeps until an event occurs. When it wakes up, it records to F-RAM until a second event occurs. After the second event, it records to the SD card until a third event occurs, usually within 30 minutes. After the third event, the SD card is unmounted and the device goes back to sleep. The SD card remains powered. The device will automatically power itself down completely when sleeping before a day is up.

    Our device already meets our design target for power. We have a desire to extend battery life as long as possible. When we have an opportunity to reduce power consumption, we take it, such as, the suggestions everyone has so graciously offered.

    We will definitely consider preallocating a large file and do raw sector writes.

  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2021-03-11 16:35

    While I use a terminal during development, Tachyon itself does not require a terminal any other time although I have used BT serial in places. Being able to use your phone to talk Tachyon to a unit on the factory floor has its advantages. I have had turn-key Tachyon code running in systems 24/7 for almost a decade now.

    Can a single P1 Tachyon instance collect data from multiple simultaneous I2C buses?
    Sure can since Tachyon itself supports multiple selectable buses from the same cog running Tachyon application code. It is easy to run a Tachyon task in other cogs so you could have 4 or 5 i2c buses running simultaneously. Creating a routine to handle an I2C device is very easy. For instance, to create a routine to write to a PCF8574 I/O expander the code is as simple as pub IO! ( data device -- ) <I2C I2C! I2C! I2C> ; which takes two parameters from the stack for the device address and data. The I2C bus speed is selectable but runs up to 1MHz without the need for PASM. BTW, Tachyon allows for small PASM modules to be loaded into the Tachyon cog as needed to supplement the Tachyon kernel.

    There's also one cog dedicated as a background task that handles timeouts and other events. Soft timers are created and linked dynamically at runtime and checked every 1ms and will optionally automatically execute code on a timeout. This task also maintains timestamps and time-of-day in software which is loaded from an RTC at reset, if it's available.

  • I will consider Tachyon for a future revision.

    Thank you

Sign In or Register to comment.