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