2
\$\begingroup\$

I am trying to write a known pattern (ie 0xFFFFFFFF or 0x00000000) on top of already written flash memory, to invalidate portions of it for a primitive file system. But it doesn't work for me on the STM32L series as it does on the STM32F series.

I am used to the STM32F family of microcontrollers, where the flash memory is erased to 0xFFFFFFFF and written with 0's. You can write anything you want to erase memory, ie

 write 0x00001234 on top of 0xFFFFFFFF -> 0x00001234

and you can write 0x00000000 (all zeros) on top of anything

 write 0x00000000 on top of 0x00001234 -> 0x0000000

I am now using the STM32L family (low power), and the flash memory is totally different. It is erased to 0x00000000, and written with 1's. However, I don't know how to reliably write all ones. For example, if I erase, I can do this

 write 0x01020304 on top of 0x00000000 -> 0x01020304

but if I try

 write 0xFFFFFFFF on top of 0x01020304 -> 0xFFFFFFBF !!!

Note that the final answer has a B in it. It is not all ones. In fact, if I write bytes 0x00 to 0xFF to a freshly erased page of memory, and then write 0xFFFFFFFFFF all over it, I get very glitchy results:

ff ff ff bf ff ff ff ff ff ff ff ff ff ff ff fb
f7 ff ff ff fd ff ff ff ff ff ff f7 ff ff ff ff
fe ff ff ff ff ff ff ff ff ff ff 7f f7 ff ff ff
ff ff ff fb ff ff ff ef ff ff ff ff ff ff ff df
fe ff ff ff ff ff ff ff ff ff ff 7f f7 ff ff ff
ff ff ff fb ff ff ff ef ff ff ff ff ff ff ff ff
ff ff ff bf ff ff ff ff ff ff ff ff ff ff ff fb
f7 ff ff ff fd ff ff ff ff ff ff f7 ff ff ff df
f7 ff ff ff fd ff ff ff ff ff ff f7 fe ff ff ff
ff ff ff bf ff ff ff ff ff ff ff ff fd ff ff ff
ff ff ff fb ff ff ff ef ff ff ff ff ff ff ff bf
fe ff ff ff ff ff ff ff ff ff ff 7f fb ff ff ff
ff ff ff fb ff ff ff ef ff ff ff ff ff ff ff bf
fe ff ff ff ff ff ff ff ff ff ff 7f ff ff ff ef
f7 ff ff ff fd ff ff ff ff ff ff f7 fe ff ff ff
ff ff ff bf ff ff ff ff ff ff ff ff fb ff ff ff

Here is the pseudo code I am using (FlashWrite is a wrapper around the STM std periph library). I tried writing a pattern of 8 writes with the bits shifted <<1 each time, and that actually gave me what I wanted (all ones) but I am not sure this is reliable.

 uint32_t pattern = 0x04030201;
 FlashErasePage(0x0801E000,FLASH_PASSWORD);
 for(int j=0;j<64;j++) {
    FlashWriteArray(0x0801E000 + 4*j,(uint8_t*)&pattern,4);
    pattern += 0x04040404;
 }

 for(int j=0;j<64;j++) {
#if 1
     // write once
     uint32_t pattern = 0xFFFFFFFF;
     FlashWriteArray(0x0801E000 + 4*j,(uint8_t*)&pattern,4);
#else
     // write shifting bit pattern
     uint32_t pattern = 0x01010101;
     for(int i=0;i<8;i++) {
        FlashWriteArray(0x0801E000 + 4*j,(uint8_t*)&pattern,4);
        pattern <<=1;
     }
#endif
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

Some types of non-volatile memory device use error-correcting logic which adds an extra few bits to each programmable chunk (e.g. 5 bits per 16, 6 per 32, 7 per 64, 8 per 128, etc.) Generally the error correction code is chosen so that all bits blank is a valid representation; in some cases, but not all, it may also be chosen such that all bits programmed is also a valid combination. For simplicity, I'll assume a code with which guards each group of 4 bits with 3 guard bits. Compute the three guard bits guard bit as being the xor of either data bits 0+1+3, 0+2+3, or 1+2+3. I'll also assume that a blank word is zero.

The 16 possible code values are thus

3210 ABC    3210 ABC    3210 ABC    3210 ABC
0000 000    0100 011    1000 111    1100 100
0001 110    0101 101    1001 001    1100 010
0010 101    0110 110    1010 010    1110 001
0011 011    0111 000    1011 100    1111 111

When a memory nybble is read, the system can see what bits ABC should be according to the table. If one of the seven bits in the word is misread, the combination of ABC bits that don't match the computed value will indicate which bit was wrong.

Suppose a memory system used the 16-bit code shown above, and one wanted to overwrite a byte value of 1110 (ECC bits 001) with a value of 1000 (ECC bits should be 111). The net effect would be that the system would write 1000 with ECC bits of 001. When the data is read back, the system would see that for a value of 1000, the ECC bits should be 111 but are instead 001. The fact that bits A and B are wrong means bit 0 of the data was wrong and should be flipped; the system would thus read the value as 1001 (whose ECC is correctly 001).

In most cases, there should be enough flexibility in the design of an error-correcting code to permit both all-bits-clear and all-bits-set to be regarded as valid combinations. Some systems do not do so, however. If an error-correcting code would require an all-bits-programmed word to have two or more of the ECC bits blank, then an attempt to obliterate a word which has those bits programmed would likely visibly fail; attempts to program many other values would likely yield a state which was only one bit error away from failure rather than two.

I really wish memory designers would allow for data to be obliterated even if they don't allow most other overwriting patterns. Especially with NAND flash, it would make some operations a lot easier.

\$\endgroup\$
4
  • \$\begingroup\$ I think I might have a "solution". If I write lots of different patterns to the same location, eventually all bits will end up 1111 including the ECC bits. Even though I don't have direct control over the ECC bits, I can eventually flip them all to 1 if I write enough random patterns. If I just write 0xFFFFFFFF once to the data, the corresponding ECC spare bits that are written are probably not all ones. But If I write enough patterns, eventually the ECC bits will all ones. And it does appear that data=0xFFFFFFFF and ECC=0xF is read out as 0xFFFFFFFF. \$\endgroup\$ Aug 28, 2013 at 17:21
  • \$\begingroup\$ @MarkLakata: Maybe that will work, but I'm a bit dubious; it would seem likely that all-bits-programmed may be only one bit error away from a non-FFFFFFFF value, and attempts to write a mixture of ones and zeroes to a byte which already contains a mixture of ones and zeroes may result in some bits being more strongly programmed than others, creating a higher-than-normal risk of bit errors. \$\endgroup\$
    – supercat
    Aug 28, 2013 at 18:10
  • \$\begingroup\$ The #else clause in my example basically writes 1 bit at a time over a byte (8 bits), and it "works" in the example case. However, you are right that it doesn't take into account some bits being stronger than other bits. \$\endgroup\$ Aug 28, 2013 at 19:28
  • \$\begingroup\$ @MarkLakata: If all of the chips in a family have historically designed their ECC to allow overwrites with all-bits-set pattern, it may be reasonable to expect that the manufacture is unlikely to change its ECC in such fashion as to disallow it. I see no reason to assume anything about ST's ECC. I don't even know a good way to tell whether writing your eight patterns will actually write all the ECC bits. If memory serves, for 4 bits, or all power-of-two data lengths other than 8 bits, a scheme that detects a single bit error can have all-bits-set and all-bits-clear as valid codewords. \$\endgroup\$
    – supercat
    Aug 28, 2013 at 19:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.