The physics, electronics, and programming of how flash memory really works
English ambiguity:
From this chat, I learned that English has some ambiguity. "Write 7 to byte #1", and "write byte #1 to 7", can mean the exact same thing in English despite having seemingly opposite directions. I am a programmer and think in code sometimes, so If you have a write operation to write a decimal 7
to address 0x01
, I would write it like this in code:
write(0x01, 7); // write(address, value)
In my wording below I would describe that as: "write byte 1 to 7", although more-clear English might say "write a 7 to byte 1".
So, when I say "write a binary 0b11111111
(all bits at HIGH voltage) to 0b00000000
(all bits at LOW voltage)", I mean this:
// some address already has a `0b11111111` in it, meaning you previously did
// this:
erase(address); // erase 4 KiB starting at address
// Now you are going to try to write this same address to a `0b00000000`
// instead, like this:
write8bits(address, 0b00000000); // write(address, value)
Another wording might be: "try to change or program a byte which contains binary 0b11111111
(all bits at HIGH voltage) to 0b00000000
(all bits at LOW voltage)".
As you read my descriptions below, just remember I'm thinking in code, and speaking kind of like I write code.
Quick answers and summary:
Since addresses of vector tables are fixed my code writes same values to same memory address of the flash on every startup.
Study what I wrote below. No new damage occurs after the initial erase operation and first write operation.
My question is would it reduce the life of flash if I write to same flash memory address on every startup/reset without erasing?
If you're writing the same exact thing to the same exact flash memory every time, with no erase cycles in between, no new damage occurs after the first write. Only the first write would actually discharge any bits (capacitors), thereby causing damage just that one time.
Here's the big take-away: write (frequently called "program" in datasheets) can only discharge. It has such a precise granularity that it can discharge single bits. Erase can only charge, and it has a horrible granularity. It can only charge sectors (ex: 4 KiB of flash memory in the Winbond W25Q128JV chip below), blocks (ex: 16 sectors, or 64 KiB in the Winbond W25Q128JV chip), or the whole chip (ex: 16 MiB in the Winbond W25Q128JV chip) at once. Sectors are generally many kilobytes. A "write" operation can never charge bits, only an "erase" operation can.
Here are some useful quotes of mine from the comments below this answer. Remember too: whether 0b11111111
represents all bits at HIGH voltage or at LOW voltage is rather arbitrary. The Winbond W25Q128JV chip below says that all bits at HIGH voltage (freshly erased) will be represented as 0b11111111
, but in most of my answer I use the opposite convention, so just pay attention to that too as I talk:
Here is my exact quote:
But, if you try to write a binary 0b11111111
(all bits at LOW voltage) to 0b00000000
(all bits at HIGH) voltage, nothing happens! Writing can NOT charge the cells, only an erase operation can! You end up with 0b11111111
still. No damage to your cells occurred. You got a no-op.
That quote is correct as-written.
But, whether a charged cell is a 0
or a 1
is rather arbitrary, and is up to the manufacturer of the flash memory [although, I now realize that erasing to a 0b11111111
is probably more common than erasing to a 0b00000000
]. So, if your flash memory uses an opposite convention, then this would also be correct as-written:
If you try to write a binary 0b00000000
(all bits at LOW voltage) to 0b11111111
(all bits at HIGH) voltage, nothing happens! Writing can NOT charge the cells, only an erase operation can! You end up with 0b00000000
still. No damage to your cells occurred. You got a no-op.
That is also correct as-written.
Details:
My question is would it reduce the life of flash if I write to same flash memory address on every startup/reset without erasing?
Let me add some insight here.
My crude understanding below gets the general principles, usage, & behaviors across, but if you really want to learn more about the physics of it, you might start by studying this article here: https://en.wikipedia.org/wiki/Flash_memory.
Here is my understanding of how flash memory really works:
- Erase: Flash memory is memory stored in microscopic capacitors. An "erase" charges all cells to a HIGH voltage, which, depending on your mcu, may be considered a binary zero (
0
) or a binary one (1
). For the rest of my analysis below, however, let's assume a bit which is charged to a HIGH voltage is considered a binary zero (0
). An "erase" cycle damages the atomic structure of the capacitor cell wall as electrons blast through it in the charging process. Erase cycles are done on entire flash memory "pages", or large chunks of memory usually many kilobytes in size, all at once. An erase is an expensive operation, both in terms of energy used and time, since a bunch of charge pumps must pump up the tiny mcu voltage to a high voltage which can charge all cells of an entire flash memory page at once in one large flood of energy to charge the capacitor bank.
- Write: A "write" can be done on a granular word (ex: 4 bytes) or byte level (granularity depends on the mcu), rather than on a large flash memory page level which is usually kilobytes. It is fast since all it has to do is short a single bit or several bits to ground to discharge the capacitors to change a HIGH voltage (
0
) to a LOW voltage (1
). "Writing" a 1
to a bit simply discharges that bit from HIGH (0
) to LOW (1
). It only changes anything if the bit was "erased" previously to charge it to a HIGH (0
) in the first place. Discharging a bit from HIGH to LOW is also a destructive process since it blasts electrons through the capacitor wall as they discharge since you shorted that cell to ground, removing matter at an atomic level as the electrons blast through. "Writing" a bit to a 0
(HIGH voltage) does absolutely nothing. It is a no-op (no operation). It is the erase cycle that sets that bit to a 0
(HIGH). It's like this:
- Writing a flash
0
(HIGH) --> 1
(LOW) = a charged bit is discharged by shorting it to ground; this is a molecularly destrutive operation.
- Writing a flash
0
(HIGH) --> 0
(HIGH) = nothing happens (writing to HIGH is a no-op); the bit is already charged, and writing cannot charge a bit; only erase can. The bit remains HIGH (0
).
- Writing a flash
1
(LOW) --> 0
(HIGH) = nothing happens (writing to HIGH is a no-op); writing cannot charge a bit; only erase can. The bit remains LOW (1
).
- Writing a flash
1
(LOW) --> 1
(LOW) = the bit is shorted to ground to discharge it to LOW (1
), but since it was already discharged, nothing happens. There are no electrons wanting to move, so this is a non-descructive operation, as the "damage" already occurred previously when this bit was discharged from a 0
(HIGH) to a 1
(LOW).
Make sense?
So, if you try to write a binary byte 0b00000000
(all bits at HIGH voltage) to 0b11111111
(all bits at LOW voltage) then it discharges all bits by shorting them to ground, bringing their voltage from HIGH to LOW and you end up with 0b11111111
. This damages the capacitor cells. If you try to write that byte to 0b11111111
again, it shorts all of their cells to ground again, but nothing happens since the cells were already discharged! No new damage occurs.
But, if you try to write a binary 0b11111111
(all bits at LOW voltage) to 0b00000000
(all bits at HIGH) voltage, nothing happens! Writing can NOT charge the cells, only an erase operation can! You end up with 0b11111111
still. No damage to your cells occurred. You got a no-op.
Therefore, damage occurs when you discharge a bit, and when you charge a bit. Charging a bit is done through an erase cycle, so you can just count how many times you erased as an estimate of the number of "damage cycles" you've imposed upon the flash memory capacitor cells.
- Standard flash memory (erasable in groups of large "pages") is generally rated up to 10,000 "write-to-1 (LOW; via discharge) / erase-to-0 (HIGH, via charge)" cycles. Refer to your datasheet for your exact number.
- EEPROM (erasable at a very granular byte or word level) flash memory is generally more-robust and can handle 100,000 write/erase cycles. Refer to your datasheet for your exact number.
Now, with this knowledge, is your "writing" really doing anything at all without an erase first?
Are you really causing any damage? If you cause it during the first write, will subsequent writes cause more damage?
You should have the tools to know those answers now.
I just consulted the datasheet for the Winbond W25Q128JV 16 MiB flash memory chip, and the terms it uses are "Page Program" (pg 36 as listed at the bottom of a PDF page), and "Sector Erase", "Block Erase", or "Chip Erase". The smallest quantity of bytes you can "program" at once is 1 byte, and the smallest quantity of bytes you can erase at once is 4 KiB. So, their terms are "program" and "erase". I simply chose to say "write" and "erase". Their erased state is all 1
s. (0b11111111
in each byte). Therefore, "programming" can only discharge bits from 1
(a HIGH voltage level) to 0
(a LOW voltage level), and "erasing" can only charge bits from 0
(a LOW voltage level) to 1
(a HIGH voltage level). "Programming" can never change a bit that is a 0
back to a 1
, no matter how hard you try. :)
Here is the "block diagram", or flash memory layout, of the Winbond W25Q128JV, from pg 10 of its datasheet. You can see in it that this particular chip has 256 blocks (numbered 0 to 255), where each block is 16 sectors (numbered 0 to 15), and each sector is 4 KiB. So, that makes the whole chip 4 KiB x 16 x 256 = 16384 KiB. Divide that by 1024 and you get 16 MiB. The smallest granularity you can program ("write") to this chip is 1 byte via the "Page Program" (0x02
) instruction on p36, and the smallest granularity you can erase is 1 sector of 4 KiB via the "Sector Erase" (0x20
) instruction on p38.

So, if you have 4 bytes that are erased to 0xFFFFFFFF
(all 1
s), and then you "program" them to 0xDEADBEEF
(0b 11011110 10101101 10111110 11101111
), they will now contain 0xDEADBEEF
(0b 11011110 10101101 10111110 11101111
). If you then "program" them to 0xBEEFDEAD
(0b 10111110 11101111 11011110 10101101
), however, those 4 bytes will NOT contain that. Rather, they will change to 0x9EAD9EAD
(0b 10011110 10101101 10011110 10101101
), as shown here:
// look for all of the attempted changes from 0 to 1.
// Programming can't do that. Only erasing can. So, they
// remain 0s.
// 1. Starting point after "erasing" is 0xffffffff.
// 2. Attempt to program to 0xdeadbeef, and you get it!
// 3. Attempt to then program to 0xbeefdead withOUT erasing again first,
// and you do NOT get it!
// 4. You end up with 0x9ead9ead instead.
11111111 11111111 11111111 11111111 ffffffff // 1.
11011110 10101101 10111110 11101111 deadbeef // 2.
10111110 11101111 11011110 10101101 beefdead // 3.
-------- -------- -------- -------- --------
10011110 10101101 10011110 10101101 9ead9ead // 4.
The code in C to attempt the above might look like this:
uint32_t addr = 0;
erase(addr); // erase 4 KiB starting at address
// `addr` to `0xffffffff` (all binary 1s)
program32bits(addr, 0xdeadbeef); // addr now contains `0xdeadbeef`
program32bits(addr, 0xbeefdead); // addr now contains `0x9ead9ead`