[fpc-pascal] FPC/Lazarus on RPi4 - How to read/write I2C connected EEPROM?

Jeffrey A. Wormsley daworm at gmail.com
Tue Apr 4 20:49:59 CEST 2023

> Page Write ...

What this means is that if you start in the middle of a 64 byte block,
let's say at byte 60 (0 based) which is on page 0, and you write 4 bytes,
then you will write into 60, 61, 62 and 63 as expected.  But if you write 6
bytes, you will write into bytes 60, 61, 62, 63 and then bytes 0 and 1 *on
page 0*.  You will not write into 64 and 65, as those are on the next
page, page 1.  Also, if you start at byte 0 (page 0) and write 128 bytes,
then the first 64 bytes will be overwritten by the second 64 bytes, so when
you send the STOP only that last 64 bytes will be written starting at byte
0, not 128 bytes onto page 0 and page 1 as you might have expected.

You can write a generic routine that starts anywhere and finishes anywhere
on the chip, as long as you keep track of the 64 byte pages.  You may have
a partial block at the beginning, zero or more full blocks, and potentially
a partial block at the end, depending on your start and end address and the
amount of data you want to write.  It is usually useful to write such a
function, because then your high level code never has to know about the
block structure.  It makes switching to different chips with different
arrangements much easier.  You write a .pas file for each specific chip,
but the "WriteData" function is the same for all of them, you only have to
change the uses clause.  OOP makes this even easier, as you create an
instance of the proper chip driver and all of the read/write calls are the
same (at some cost to code size).  Usually, when I do this in C, I create
groups of #defines for the various page sizes, memory size, erase sector
size, and so on, and use an #ifdef to select the correct set for the chip
I'm using, and the code is the same for almost all chips, I don't even need
different source files, just a master .h with all of the chips I support.
I'm sure this should be easy enough to do in Pascal as well, but I must
confess I don't often use Pascal for my embedded work, usually only on the
PC side of things.


On Mon, Apr 3, 2023 at 4:41 PM Bo Berglund via fpc-pascal <
fpc-pascal at lists.freepascal.org> wrote:

> On Mon, 3 Apr 2023 14:37:48 -0400, "Jeffrey A. Wormsley via fpc-pascal"
> <fpc-pascal at lists.freepascal.org> wrote:
> >I noticed you put the part number in the original email.
> >
> >Interestingly, the data sheet mentions 64 byte pages, and 1,000,000 erase
> >cycles, but does not mention the need to erase a page before writing.  So
> >perhaps this part does not have that restriction.
> >
> >If you're making a library specifically for this part, then I guess you
> >don't have to worry about this.  If you're making a library for generic
> >eeprom support, I think you might want to consider that not all parts
> >behave this way.
> You alerted me to the page size which I have been mis-reading until now it
> seems
> like...
> This 128 kbit part is apparently built like this:
> - 16384 memory bytes
> - Organized as 256 64 byte "pages"
> - The page write buffer is 64 bytes, i.e. the same size as a memory "page"
> Then there is a discusion about the way the write buffer maps onto the
> memory
> array, which I didn't understand fully...
> [quote]
> Page Write
> By continuing to load data into the Page Write Buffer after
> the 1st data byte and before issuing the STOP condition, up
> to  64  bytes  can  be  written  simultaneously  during  one
> internal Write cycle (Figure 8). If more data bytes are loaded
> than locations available to the end of page, then loading will
> continue from the beginning of page, i.e. the page address is
> latched and the address count automatically increments to
> and then wraps-around at the page boundary. Previously
> loaded data can thus be overwritten by new data. What is
> eventually written to memory reflects the latest Page Write
> Buffer contents. Only data loaded within the most recent
> Page Write sequence will be written to memory.
> [/quote]
> Maybe it is like this:
> The page write buffer is 64 bytes and incoming data are written to the
> buffer
> starting at an address (I assume) within that buffer given by the last 6
> bits of
> the address being written in the command.
> This to me reads like the same place in the buffer as eventually in the
> memory
> *page* when written.
> And if one continues to send data to the part after reaching the end of the
> buffer it writes those to the beginning of the buffer instead (wrap-around,
> which is bad and will destroy data).
> Finally when the transfer is ended (STOP condition) then the buffer
> somehow is
> moved onto the main memory.
> Here I am unclear on how it works, one possibility would be that there is
> some
> bit field or similar on chip that marks bytes in the buffer that have been
> written by incoming data. Then all other bytes can be filled from the page
> in
> main memory by reading those to unwritten locations in the buffer.
> Or else maybe simpler: when the write starts and the page is determined the
> buffer may be filled from a main memory page copy and then overwritten by
> incoming data...
> Now the buffer has a content that is the same as in main memory except for
> the
> data that were sent in.
> So then the part may erase the page in main memory as you stated and once
> that
> is done write the buffer content on top of the page that is now blanked
> out to
> 0xff cells.
> I cannot think of any other procedure that matches what the datasheet
> says..
> And if it is like this you are right that the cells must be bulk erased
> before
> one can write random data there...
> But it is handled without the user having to do anything at all...
> Now I have to go back into my code and adjust the handling for the write
> buffer,
> since I can only send in at most 64 bytes at a time and that only if the
> write
> starts at 6 bit address 0 in the buffer. Otherwise less data can be
> written in
> each cycle.
> I am transfering the data to write to the write procedure as a TBytes
> array of
> random size and the code needs to start (in most cases) by sending in a
> smaller
> than 64 byte write packet and then fill with full 64 byte pages and then
> finalize with a short page at the end of the write procedure. Unless
> everything
> happens to align on 64 byte address boundaries...
> Getting a bit dizzy...
> But still the main Freepascal interface into Linux that I got from GitHub
> works
> so this is just a case of sequencing the commands correctly! :-)
> Thanks for making me read closer into the datasheet!
> --
> Bo Berglund
> Developer in Sweden
> _______________________________________________
> fpc-pascal maillist  -  fpc-pascal at lists.freepascal.org
> https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freepascal.org/pipermail/fpc-pascal/attachments/20230404/b011d75a/attachment-0001.htm>

More information about the fpc-pascal mailing list