Figured out why these mismatches occur.
TLDR: Those pages aren't using ECC.
Page 0xF80…0xFFF store the lock bits for the OTP pages 0…63. Since the lock bits must be programmable multiple times (to go from read/write → read-only → no-access), they do not use the harware ECC support. Instead, they are read (and written) in raw form only. Instead, each row stores 3x copies of a single byte. This allows a later programming request to set additional bits, which would be prevented when using ECC codes.
I will have to update the code to show rows 0xF80…0xFFF as 100% OK when they store three identical bytes. Moreover, the ECC-corrected reads do not have valid meaning, so I will update those to be masked from the output.
I also found the SDK code (and adapted it) to verify the ECC from the data read in raw form, and verified its functionality on godbolt.org. Thus, can simplify the code further.
There is still a few edge cases which make it impossible to 100% reliably auto-detect that the data was stored in triplicate vs. stored with ECC. Specifically, there are two values that, when stored as triple-encoded bytes, have valid ECC byte. If allowing for the OTP row to have a single-bit error, then there are an additional sixteen (16) values that, when read from the OTP row with a single-bit error, might be either valid ECC stored values, or a triple-encoded byte.
The situations I considered can be found on godbolt.org. This shows a very strong indicator can be determined, just from the raw data, as to whether the data was intended to be stored with ECC, or intended to be stored as a triple-encoded single byte.
Raw OTP data that needs special consideration.
Pages from 0xF80
… 0xFFF
are always 3x-byte encoded.
User pages will need a “best guess”?
Raw 24 bits | 3x byte | Bitflip needed |
---|---|---|
0x000000 |
0x00 |
ECC is correct |
0x171717 |
0x17 |
ECC is correct |
0x020212 |
0x02 |
0x000010 |
0x010501 |
0x01 |
0x000400 |
0x040504 |
0x04 |
0x000100 |
0x070747 |
0x07 |
0x000040 |
0x101050 |
0x10 |
0x000040 |
0x131213 |
0x13 |
0x000100 |
0x161216 |
0x16 |
0x000400 |
0x151505 |
0x15 |
0x000010 |
0x2a282a |
0x2a |
0x000200 |
0x212929 |
0x29 |
0x080000 |
0x2c2c0c |
0x2c |
0x000020 |
0x2f2faf |
0x2f |
0x000080 |
0x3838b8 |
0x38 |
0x000080 |
0x3b3b1b |
0x3b |
0x000020 |
0x363e3e |
0x3e |
0x080000 |
0x3d3f3d |
0x3d |
0x000200 |
Expect more changes incoming…