Marttyn
Joined: 06 Mar 2015 Posts: 28 Location: Spain
|
FASTER I2C external EEPROM writing library! |
Posted: Wed Feb 05, 2020 6:40 am |
|
|
Hi!
Ive been working on a project that needs to write to an external EEPROM, and then continue doing "stuff" very quickly. The problem for me was not the time from write to write (usually 5ms). My program writes every 20ms.
My problem was to wait 5ms after the I2C data was sent to the EEPROM.
The key point is that once you send the data, the EEPROM "writes itself alone", you can stay there or you can be doing other things... so I preferred to do other things instead of waiting :D
With this in mind I improved libraries for 256K and 1024K (the ones i use the most). Also implemented page read and write, and a function to show over serial whats inside the EEPROM with a nice format (thanks to http://www.ccsinfo.com/forum/viewtopic.php?t=58490 for helping find to "compile or not").
What i did to improve speed? Instead of waiting AFTER writing, my library waits BEFORE writing... Wait, what!?
Usually EEPROM libraries write, and then polls to the EEPROM for the finish.
While my approach simply writes, and then exit, without polling.
Instead the read and write functions check if the EEPROM is ready before sending a new read/write command. If the EEPROM is still writing from previous operations, then wait until finish, and then continue.
This way, the time for a single write operation is very fast:
Enter function -> Check if EEPROM is busy -> Write -> Exit
No waiting at all! This save us 3-5ms of waiting.
While consecutive writings will still needs to wait for the previous operation to finish.
I did some research, and this technique is not commented anywhere. Although Microchip has an application note about how to use EEPROMs and how to improve speed: http://ww1.microchip.com/downloads/en/Appnotes/01028B.pdf
To be honest, as no one used this approach, and further Microchip don't talk about this anywhere, I've thought that this would not work. But after many test, this seems to work consistently, and I'm using it on a production product.
This are some test made at 400Khz bus speed with PIC hardware I2C and 32Mhz internal oscillator, using a 24AA1025 memory:
Quote: | - Start -
- 16 BYTES OLD WRITE -
Byte 0: 4205 uS
Byte 1: 4206 uS
Byte 2: 4206 uS
Byte 3: 4205 uS
Byte 4: 4205 uS
Byte 5: 4206 uS
Byte 6: 4206 uS
Byte 7: 4205 uS
Byte 8: 4205 uS
Byte 9: 4206 uS
Byte 10: 4206 uS
Byte 11: 4205 uS
Byte 12: 4205 uS
Byte 13: 4206 uS
Byte 14: 4206 uS
Byte 15: 4204 uS
TOTAL: 0 Sec 68 mS 478 uS
- 16 BYTES NEW WRITE -
Byte 0: 190 uS
Byte 1: 4022 uS
Byte 2: 4022 uS
Byte 3: 4022 uS
Byte 4: 4022 uS
Byte 5: 4021 uS
Byte 6: 4021 uS
Byte 7: 4022 uS
Byte 8: 4022 uS
Byte 9: 4022 uS
Byte 10: 4022 uS
Byte 11: 4022 uS
Byte 12: 4022 uS
Byte 13: 4021 uS
Byte 14: 4021 uS
Byte 15: 4022 uS
TOTAL: 0 Sec 61 mS 707 uS
- 16 PAGES WRITE (128 bytes/page) -
Page 0: 4119 uS
Page 1: 7951 uS
Page 2: 7951 uS
Page 3: 7951 uS
Page 4: 7951 uS
Page 5: 7951 uS
Page 6: 7951 uS
Page 7: 7951 uS
Page 8: 7958 uS
Page 9: 7953 uS
Page 10: 7953 uS
Page 11: 7952 uS
Page 12: 7953 uS
Page 13: 7953 uS
Page 14: 7953 uS
Page 15: 7952 uS
TOTAL: 0 Sec 124 mS 616 uS
- FULL EEPROM WRITE -
TOTAL: 4 Sec 149 mS 403 uS |
For the "old" write, a single write spend 4205 uS, every single byte wrote.
While for "new" write, the first byte took only 190 uS!! And the next ones 4022 uS.
A full EEPROM write takes a little bit more than 4 seconds for a total of 131,072 bytes.
This means, that if you write a byte every 4-5 ms and up, then your uC will be taking only 190us to perform the write.
Remember: this library will not improve in the time taken by the memory to perform the write, but will free your uC to do whatever you want while the write happens.
You can find my library, and also the example program of the time measurement on Github: https://github.com/ideaalab/eeprom_library
Also have some other libraries, they are not perfect, but they work for me
Hope you find this useful! |
|